那艺娜维基
ladynanawiki
https://ladynana.miraheze.org/wiki/%E9%A6%96%E9%A1%B5
MediaWiki 1.42.1
first-letter
Media
Special
Talk
User
User talk
那艺娜维基
那艺娜维基 talk
File
File talk
MediaWiki
MediaWiki talk
Template
Template talk
Help
Help talk
Category
Category talk
Campaign
Campaign talk
Module
Module talk
Translations
Translations talk
LTA
LTA talk
那艺娜维基:Void
4
18
31
2011-06-27T23:22:38Z
zhwp>Kegns
0
保护 Template:Void: [[WP:HRT]] ([edit=sysop] (无期) [move=sysop] (无期))
wikitext
text/x-wiki
<noinclude>{{doc}}</noinclude>
2ad0a7aac7bb5b51850ca5d508fcde851272e224
Template:Void
10
43
81
2011-06-27T23:22:38Z
zhwp>Kegns
0
保护 Template:Void: [[WP:HRT]] ([edit=sysop] (无期) [move=sysop] (无期))
wikitext
text/x-wiki
<noinclude>{{doc}}</noinclude>
2ad0a7aac7bb5b51850ca5d508fcde851272e224
Template:T1
10
100
194
2012-02-27T05:29:56Z
zhwp>Liangent
0
wikitext
text/x-wiki
#REDIRECT [[Template:Tl]] {{错字重定向}}
be295331905847cbb58c82c268a1165f8cd1dad5
Template:Str left
10
213
444
2012-08-08T12:20:44Z
zhwp>Liangent
0
Liangent移动页面[[Template:Left]]至[[Template:Str left]]覆盖重定向
wikitext
text/x-wiki
<includeonly>{{ {{{|safesubst:}}}padleft:|{{{2|1}}}|{{{1}}}}}</includeonly><noinclude>
{{documentation}}
</noinclude>
9c0bdb76d3fd64ecd8af888df4ec235e5aec0b33
Template:MONTHNUMBER
10
231
481
2014-01-25T08:17:20Z
zhwp>Lanwi1
0
移除{{pp-template}}
wikitext
text/x-wiki
{{#if:{{{1|}}}|{{#switch:{{lc:{{{1}}}}}|january|一月|jan=1|february|二月|feb=2|march|三月|mar=3|apr|四月|april=4|五月|may=5|june|六月|jun=6|july|七月|jul=7|august|八月|aug=8|september|九月|sep=9|october|十月|oct=10|november|十一月|nov=11|december|十二月|dec=12|{{#ifexpr:{{{1}}}<0|{{#ifexpr:(({{{1}}})round 0)!=({{{1}}})|{{#expr:12-(((0.5-({{{1}}}))round 0)mod 12)}}|{{#expr:12-(((11.5-({{{1}}}))round 0)mod 12)}}}}|{{#expr:(((10.5+{{{1}}})round 0)mod 12)+1}}}}}}|Missing required parameter 1=''month''!}}<noinclude>{{doc}}</noinclude>
23dfd4382f37871a866bf3d27ff8140ea7b481ee
Module:Pagetype
828
83
160
2015-02-04T04:54:27Z
zhwp>RalfX
0
保护 模块:Pagetype([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- PAGETYPE --
-- --
-- This is a meta-module intended to replace {{pagetype}} and similar --
-- templates. It automatically detects namespaces, and allows for a --
-- great deal of customisation. It can easily be ported to other --
-- wikis by changing the values in the [[Module:Pagetype/config]]. --
-- --
--------------------------------------------------------------------------------
-- Load config.
local cfg = mw.loadData('Module:Pagetype/config')
-- Load required modules.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local nsDetectModule = require('Module:Namespace detect')
local nsDetect = nsDetectModule._main
local getParamMappings = nsDetectModule.getParamMappings
local getPageObject = nsDetectModule.getPageObject
local p = {}
local function shallowCopy(t)
-- Makes a shallow copy of a table.
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
local function checkPagetypeInput(namespace, val)
-- Checks to see whether we need the default value for the given namespace,
-- and if so gets it from the pagetypes table.
-- The yesno function returns true/false for "yes", "no", etc., and returns
-- val for other input.
local ret = yesno(val, val)
if ret and type(ret) ~= 'string' then
ret = cfg.pagetypes[namespace]
end
return ret
end
local function getPagetypeFromClass(class, param, aliasTable, default)
-- Gets the pagetype from a class specified from the first positional
-- parameter.
param = yesno(param, param)
if param ~= false then -- No check if specifically disallowed.
for _, alias in ipairs(aliasTable) do
if class == alias then
if type(param) == 'string' then
return param
else
return default
end
end
end
end
end
local function getNsDetectValue(args)
-- Builds the arguments to pass to [[Module:Namespace detect]] and returns
-- the result.
-- Get the default values.
local ndArgs = {}
local defaultns = args[cfg.defaultns]
if defaultns == cfg.defaultnsAll then
ndArgs = shallowCopy(cfg.pagetypes)
else
local defaultnsArray
if defaultns == cfg.defaultnsExtended then
defaultnsArray = cfg.extendedNamespaces
elseif defaultns == cfg.defaultnsNone then
defaultnsArray = {}
else
defaultnsArray = cfg.defaultNamespaces
end
for _, namespace in ipairs(defaultnsArray) do
ndArgs[namespace] = cfg.pagetypes[namespace]
end
end
--[[
-- Add custom values passed in from the arguments. These overwrite the
-- defaults. The possible argument names are fetched from
-- Module:Namespace detect automatically in case new namespaces are
-- added. Although we accept namespace aliases as parameters, we only pass
-- the local namespace name as a parameter to Module:Namespace detect.
-- This means that the "image" parameter can overwrite defaults for the
-- File: namespace, which wouldn't work if we passed the parameters through
-- separately.
--]]
local mappings = getParamMappings()
for ns, paramAliases in pairs(mappings) do
-- Copy the aliases table, as # doesn't work with tables returned from
-- mw.loadData.
paramAliases = shallowCopy(paramAliases)
local paramName = paramAliases[1]
-- Iterate backwards along the array so that any values for the local
-- namespace names overwrite those for namespace aliases.
for i = #paramAliases, 1, -1 do
local paramAlias = paramAliases[i]
local ndArg = checkPagetypeInput(paramAlias, args[paramAlias])
if ndArg == false then
-- If any arguments are false, convert them to nil to protect
-- against breakage by future changes to
-- [[Module:Namespace detect]].
ndArgs[paramName] = nil
elseif ndArg then
ndArgs[paramName] = ndArg
end
end
end
-- Check for disambiguation-class and N/A-class pages in mainspace.
if ndArgs.main then
local class = args[1]
if type(class) == 'string' then
-- Put in lower case so e.g. "Dab" and "dab" will both match.
class = mw.ustring.lower(class)
end
local dab = getPagetypeFromClass(
class,
args[cfg.dab],
cfg.dabAliases,
cfg.dabDefault
)
if dab then
ndArgs.main = dab
else
local na = getPagetypeFromClass(
class,
args[cfg.na],
cfg.naAliases,
cfg.naDefault
)
if na then
ndArgs.main = na
end
end
end
-- If there is no talk value specified, use the corresponding subject
-- namespace for talk pages.
if not ndArgs.talk then
ndArgs.subjectns = true
end
-- Add the fallback value. This can also be customised, but it cannot be
-- disabled.
local other = args[cfg.other]
-- We will ignore true/false/nil results from yesno here, but using it
-- anyway for consistency.
other = yesno(other, other)
if type(other) == 'string' then
ndArgs.other = other
else
ndArgs.other = cfg.otherDefault
end
-- Allow custom page values.
ndArgs.page = args.page
return nsDetect(ndArgs)
end
local function detectRedirects(args)
local redirect = args[cfg.redirect]
-- The yesno function returns true/false for "yes", "no", etc., and returns
-- redirect for other input.
redirect = yesno(redirect, redirect)
if redirect == false then
-- Detect redirects unless they have been explicitly disallowed with
-- "redirect=no" or similar.
return
end
local pageObject = getPageObject(args.page)
-- If we are using subject namespaces elsewhere, do so here as well.
if pageObject
and not yesno(args.talk, true)
and args[cfg.defaultns] ~= cfg.defaultnsAll
then
pageObject = getPageObject(
pageObject.subjectNsText .. ':' .. pageObject.text
)
end
-- Allow custom values for redirects.
if pageObject and pageObject.isRedirect then
if type(redirect) == 'string' then
return redirect
else
return cfg.redirectDefault
end
end
end
function p._main(args)
local redirect = detectRedirects(args)
if redirect then
return redirect
else
return getNsDetectValue(args)
end
end
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
return p
4e76ed8318e724693304c0ca2063b36b0890825a
Template:Efn-ur
10
191
400
2015-11-22T11:06:00Z
zhwp>Cdip150
0
wikitext
text/x-wiki
<includeonly>{{efn|name={{{name|}}}|group=upper-roman|1={{{1|}}}}}</includeonly><noinclude>
{{documentation|Template:notelist/doc}}
</noinclude>
73c8ddd55bffed98bf9b211a8a0cdbba28a1040a
Template:Notelist-ur
10
192
402
2015-11-22T11:16:22Z
zhwp>Cdip150
0
wikitext
text/x-wiki
<includeonly>{{notelist|1={{{1|{{{refs|{{{notes|}}}}}}}}}|group=upper-roman}}</includeonly><noinclude>
{{documentation|Template:Notelist/doc}}
</noinclude>
64ef89ca9259c7c15888a74981a6882f7839ebca
Template:Script/Tifinagh
10
328
681
2016-04-17T10:34:59Z
zhwp>Great Brightstar
0
wikitext
text/x-wiki
<span class="script-tifinagh" style="font-family: 'DejaVu Sans', Ebrima, FreeSans, 'Noto Sans Tifinagh'">{{{1}}}</span><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
c27b99d4ad79f86a6d26ff28d6c17fcfaa8efd1e
那艺娜维基:Noredirect
4
27
49
2016-06-13T14:01:29Z
zhwp>Quest for Truth
0
Quest for Truth 已移動頁面 [[Template:Noredirect]] 至 [[Template:No redirect]]:更易閱讀
wikitext
text/x-wiki
#重定向 [[Template:No redirect]]
7bbca779757c40530991fa4afadd831104b1287e
Template:Noredirect
10
55
103
2016-06-13T14:01:29Z
zhwp>Quest for Truth
0
Quest for Truth 已移動頁面 [[Template:Noredirect]] 至 [[Template:No redirect]]:更易閱讀
wikitext
text/x-wiki
#重定向 [[Template:No redirect]]
7bbca779757c40530991fa4afadd831104b1287e
Template:Templatedataheader
10
208
434
2016-07-07T06:49:27Z
zhwp>Xqbot
0
机器人:修正双重重定向至[[Template:TemplateData header]]
wikitext
text/x-wiki
#重定向 [[Template:TemplateData header]]
ed82fd29d375c3f39a93c690ac9d02cf1cebcb04
Template:If empty
10
248
513
2016-08-08T15:28:01Z
zhwp>Peacearth
0
// Edit via Wikiplus
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:If empty|main}}<noinclude>{{Documentation}}</noinclude>
745940b7bdde8a1585c887ee4ee5ce81d98461a4
那艺娜维基:请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。
4
26
47
2016-10-19T22:22:24Z
zhwp>DreamLiner
0
[[WP:AES|←]]重定向到[[Template:Void]]
wikitext
text/x-wiki
#REDIRECT [[Template:Void]]
90ff2dc1111160c936f3a960d5c2158a7628aed5
Template:请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。
10
54
101
2016-10-19T22:22:24Z
zhwp>DreamLiner
0
[[WP:AES|←]]重定向到[[Template:Void]]
wikitext
text/x-wiki
#REDIRECT [[Template:Void]]
90ff2dc1111160c936f3a960d5c2158a7628aed5
那艺娜维基:Lan
4
9
13
2017-01-17T03:46:12Z
zhwp>Alexander Misel
0
EP
wikitext
text/x-wiki
<includeonly>{{#invoke:lan|main}}</includeonly><noinclude>{{模板文档}}</noinclude>
9a0c6ae29e4b3d5782f1580fbccc37393902b49f
Template:Lan
10
31
57
2017-01-17T03:46:12Z
zhwp>Alexander Misel
0
EP
wikitext
text/x-wiki
<includeonly>{{#invoke:lan|main}}</includeonly><noinclude>{{模板文档}}</noinclude>
9a0c6ae29e4b3d5782f1580fbccc37393902b49f
Template:Transclude
10
82
158
2017-01-25T03:53:06Z
zhwp>Antigng
0
bot: massreplace: "<noinclude>{{pp-template|small=yes}}</noinclude>" ->"(null)"
wikitext
text/x-wiki
{{#switch: {{NAMESPACE: {{{1}}} }}
|#default = {{FULLPAGENAME: {{{1}}} }} <!-- eg "User:Foo" -->
|{{ns:0}} =
{{#ifeq: {{NAMESPACE: {{{1}}} }} | {{NAMESPACE: Template{{{1}}} }}
| Template:{{{1}}} <!-- no leading colon, eg "Foo" -->
| {{PAGENAME: {{{1}}} }} <!-- leading colon, eg ":Foo", so we want the article -->
}}
}}<noinclude>
{{documentation}}
</noinclude>
d0239e71e5745cd0d4efd032cee07341e111376b
Transclude
0
288
599
2017-01-25T03:53:06Z
zhwp>Antigng
0
bot: massreplace: "<noinclude>{{pp-template|small=yes}}</noinclude>" ->"(null)"
wikitext
text/x-wiki
{{#switch: {{NAMESPACE: {{{1}}} }}
|#default = {{FULLPAGENAME: {{{1}}} }} <!-- eg "User:Foo" -->
|{{ns:0}} =
{{#ifeq: {{NAMESPACE: {{{1}}} }} | {{NAMESPACE: Template{{{1}}} }}
| Template:{{{1}}} <!-- no leading colon, eg "Foo" -->
| {{PAGENAME: {{{1}}} }} <!-- leading colon, eg ":Foo", so we want the article -->
}}
}}<noinclude>
{{documentation}}
</noinclude>
d0239e71e5745cd0d4efd032cee07341e111376b
Template:內聯模板文件
10
282
588
2017-03-02T20:04:48Z
zhwp>Zyksnowy
0
wikitext
text/x-wiki
#重定向 [[Template:Documentation_subpage]]
{{別名重定向}}{{模板重定向}}
1528d83c7e5427f26645681e049a0887baf9d260
Template:Nottest
10
58
110
2017-03-08T07:32:40Z
zhwp>Iokseng
0
Iokseng 已移動頁面 [[Template:Nottest]] 至 [[Template:Not a sandbox]]
wikitext
text/x-wiki
#重定向 [[Template:Not a sandbox]]
2bb1a24d63bd44c5065444f91a511008c03ce2a3
Template:ISO 639 name en
10
174
352
2017-09-04T15:26:11Z
zhwp>Antigng
0
bot: massreplace: "[[en:{{FULLPAGENAME}}]]" ->"(null)"
wikitext
text/x-wiki
英語<noinclude>
{{ISO 639 name conversion template doc|{{ {{PAGENAME}} }}|en}}
</noinclude>
873f783ebcee476b68129cda93a2d1e4ba60239c
Module:Namespace detect
828
85
164
2017-09-06T03:06:09Z
zhwp>Xiplus
0
已保护“[[模块:Namespace detect]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--[[
--------------------------------------------------------------------------------
-- --
-- NAMESPACE DETECT --
-- --
-- This module implements the {{namespace detect}} template in Lua, with a --
-- few improvements: all namespaces and all namespace aliases are supported, --
-- and namespace names are detected automatically for the local wiki. The --
-- module can also use the corresponding subject namespace value if it is --
-- used on a talk page. Parameter names can be configured for different wikis --
-- by altering the values in the "cfg" table in --
-- Module:Namespace detect/config. --
-- --
--------------------------------------------------------------------------------
--]]
local data = mw.loadData('Module:Namespace detect/data')
local argKeys = data.argKeys
local cfg = data.cfg
local mappings = data.mappings
local yesno = require('Module:Yesno')
local mArguments -- Lazily initialise Module:Arguments
local mTableTools -- Lazily initilalise Module:TableTools
local ustringLower = mw.ustring.lower
local p = {}
local function fetchValue(t1, t2)
-- Fetches a value from the table t1 for the first key in array t2 where
-- a non-nil value of t1 exists.
for i, key in ipairs(t2) do
local value = t1[key]
if value ~= nil then
return value
end
end
return nil
end
local function equalsArrayValue(t, value)
-- Returns true if value equals a value in the array t. Otherwise
-- returns false.
for i, arrayValue in ipairs(t) do
if value == arrayValue then
return true
end
end
return false
end
function p.getPageObject(page)
-- Get the page object, passing the function through pcall in case of
-- errors, e.g. being over the expensive function count limit.
if page then
local success, pageObject = pcall(mw.title.new, page)
if success then
return pageObject
else
return nil
end
else
return mw.title.getCurrentTitle()
end
end
-- Provided for backward compatibility with other modules
function p.getParamMappings()
return mappings
end
local function getNamespace(args)
-- This function gets the namespace name from the page object.
local page = fetchValue(args, argKeys.demopage)
if page == '' then
page = nil
end
local demospace = fetchValue(args, argKeys.demospace)
if demospace == '' then
demospace = nil
end
local subjectns = fetchValue(args, argKeys.subjectns)
local ret
if demospace then
-- Handle "demospace = main" properly.
if equalsArrayValue(argKeys.main, ustringLower(demospace)) then
ret = mw.site.namespaces[0].name
else
ret = demospace
end
else
local pageObject = p.getPageObject(page)
if pageObject then
if pageObject.isTalkPage then
-- Get the subject namespace if the option is set,
-- otherwise use "talk".
if yesno(subjectns) then
ret = mw.site.namespaces[pageObject.namespace].subject.name
else
ret = 'talk'
end
else
ret = pageObject.nsText
end
else
return nil -- return nil if the page object doesn't exist.
end
end
ret = ret:gsub('_', ' ')
return ustringLower(ret)
end
function p._main(args)
-- Check the parameters stored in the mappings table for any matches.
local namespace = getNamespace(args) or 'other' -- "other" avoids nil table keys
local params = mappings[namespace] or {}
local ret = fetchValue(args, params)
--[[
-- If there were no matches, return parameters for other namespaces.
-- This happens if there was no text specified for the namespace that
-- was detected or if the demospace parameter is not a valid
-- namespace. Note that the parameter for the detected namespace must be
-- completely absent for this to happen, not merely blank.
--]]
if ret == nil then
ret = fetchValue(args, argKeys.other)
end
return ret
end
function p.main(frame)
mArguments = require('Module:Arguments')
local args = mArguments.getArgs(frame, {removeBlanks = false})
local ret = p._main(args)
return ret or ''
end
function p.table(frame)
--[[
-- Create a wikitable of all subject namespace parameters, for
-- documentation purposes. The talk parameter is optional, in case it
-- needs to be excluded in the documentation.
--]]
-- Load modules and initialise variables.
mTableTools = require('Module:TableTools')
local namespaces = mw.site.namespaces
local cfg = data.cfg
local useTalk = type(frame) == 'table'
and type(frame.args) == 'table'
and yesno(frame.args.talk) -- Whether to use the talk parameter.
-- Get the header names.
local function checkValue(value, default)
if type(value) == 'string' then
return value
else
return default
end
end
local nsHeader = checkValue(cfg.wikitableNamespaceHeader, 'Namespace')
local aliasesHeader = checkValue(cfg.wikitableAliasesHeader, 'Aliases')
-- Put the namespaces in order.
local mappingsOrdered = {}
for nsname, params in pairs(mappings) do
if useTalk or nsname ~= 'talk' then
local nsid = namespaces[nsname].id
-- Add 1, as the array must start with 1; nsid 0 would be lost otherwise.
nsid = nsid + 1
mappingsOrdered[nsid] = params
end
end
mappingsOrdered = mTableTools.compressSparseArray(mappingsOrdered)
-- Build the table.
local ret = '{| class="wikitable"'
.. '\n|-'
.. '\n! ' .. nsHeader
.. '\n! ' .. aliasesHeader
for i, params in ipairs(mappingsOrdered) do
for j, param in ipairs(params) do
if j == 1 then
ret = ret .. '\n|-'
.. '\n| <code>' .. param .. '</code>'
.. '\n| '
elseif j == 2 then
ret = ret .. '<code>' .. param .. '</code>'
else
ret = ret .. ', <code>' .. param .. '</code>'
end
end
end
ret = ret .. '\n|-'
.. '\n|}'
return ret
end
return p
a4757000273064f151f0f22dc0e139092e5ff443
Module:Namespace detect/config
828
69
132
2017-09-06T03:06:44Z
zhwp>Xiplus
0
已保护“[[模块:Namespace detect/config]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect configuration data --
-- --
-- This module stores configuration data for Module:Namespace detect. Here --
-- you can localise the module to your wiki's language. --
-- --
-- To activate a configuration item, you need to uncomment it. This means --
-- that you need to remove the text "-- " at the start of the line. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. Values added --
-- here will work in addition to the default English parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- cfg.foo = 'parameter name' --
-- --
-- To add multiple names, you can use this format: --
-- --
-- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} --
--------------------------------------------------------------------------------
---- This parameter displays content for the main namespace:
-- cfg.main = 'main'
---- This parameter displays in talk namespaces:
-- cfg.talk = 'talk'
---- This parameter displays content for "other" namespaces (namespaces for which
---- parameters have not been specified):
-- cfg.other = 'other'
---- This parameter makes talk pages behave as though they are the corresponding
---- subject namespace. Note that this parameter is used with [[Module:Yesno]].
---- Edit that module to change the default values of "yes", "no", etc.
-- cfg.subjectns = 'subjectns'
---- This parameter sets a demonstration namespace:
-- cfg.demospace = 'demospace'
---- This parameter sets a specific page to compare:
cfg.demopage = 'page'
--------------------------------------------------------------------------------
-- Table configuration --
-- These configuration items allow customisation of the "table" function, --
-- used to generate a table of possible parameters in the module --
-- documentation. --
--------------------------------------------------------------------------------
---- The header for the namespace column in the wikitable containing the list of
---- possible subject-space parameters.
-- cfg.wikitableNamespaceHeader = 'Namespace'
---- The header for the wikitable containing the list of possible subject-space
---- parameters.
-- cfg.wikitableAliasesHeader = 'Aliases'
--------------------------------------------------------------------------------
-- End of configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
0e4ff08d13c4b664d66b32c232deb129b77c1a56
Module:Namespace detect/data
828
68
130
2017-09-06T03:06:49Z
zhwp>Xiplus
0
已保护“[[模块:Namespace detect/data]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect data --
-- This module holds data for [[Module:Namespace detect]] to be loaded per --
-- page, rather than per #invoke, for performance reasons. --
--------------------------------------------------------------------------------
local cfg = require('Module:Namespace detect/config')
local function addKey(t, key, defaultKey)
if key ~= defaultKey then
t[#t + 1] = key
end
end
-- Get a table of parameters to query for each default parameter name.
-- This allows wikis to customise parameter names in the cfg table while
-- ensuring that default parameter names will always work. The cfg table
-- values can be added as a string, or as an array of strings.
local defaultKeys = {
'main',
'talk',
'other',
'subjectns',
'demospace',
'demopage'
}
local argKeys = {}
for i, defaultKey in ipairs(defaultKeys) do
argKeys[defaultKey] = {defaultKey}
end
for defaultKey, t in pairs(argKeys) do
local cfgValue = cfg[defaultKey]
local cfgValueType = type(cfgValue)
if cfgValueType == 'string' then
addKey(t, cfgValue, defaultKey)
elseif cfgValueType == 'table' then
for i, key in ipairs(cfgValue) do
addKey(t, key, defaultKey)
end
end
cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more.
end
local function getParamMappings()
--[[
-- Returns a table of how parameter names map to namespace names. The keys
-- are the actual namespace names, in lower case, and the values are the
-- possible parameter names for that namespace, also in lower case. The
-- table entries are structured like this:
-- {
-- [''] = {'main'},
-- ['wikipedia'] = {'wikipedia', 'project', 'wp'},
-- ...
-- }
--]]
local mappings = {}
local mainNsName = mw.site.subjectNamespaces[0].name
mainNsName = mw.ustring.lower(mainNsName)
mappings[mainNsName] = mw.clone(argKeys.main)
mappings['talk'] = mw.clone(argKeys.talk)
for nsid, ns in pairs(mw.site.subjectNamespaces) do
if nsid ~= 0 then -- Exclude main namespace.
local nsname = mw.ustring.lower(ns.name)
local canonicalName = mw.ustring.lower(ns.canonicalName)
mappings[nsname] = {nsname}
if canonicalName ~= nsname then
table.insert(mappings[nsname], canonicalName)
end
for _, alias in ipairs(ns.aliases) do
table.insert(mappings[nsname], mw.ustring.lower(alias))
end
end
end
return mappings
end
return {
argKeys = argKeys,
cfg = cfg,
mappings = getParamMappings()
}
d224f42a258bc308ef3ad8cc8686cd7a4f47d005
Template:Tsl
10
306
637
2017-09-23T22:40:55Z
zhwp>Xiplus
0
已保护“[[Template:Tsl]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
#REDIRECT [[Template:Translink]]
{{縮寫重定向}}
{{模板重定向}}
f4c0065c4503db756be96de5c746c28184cf9f1a
Module:Unsubst
828
261
544
2017-09-25T14:38:07Z
zhwp>Xiplus
0
已保护“[[模块:Unsubst]]”:高風險模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
local p = {}
local specialParams = {
['$N'] = 'template name', -- Deprecated, but keeping until it is removed from transcluding templates
['$B'] = 'template content',
}
p[''] = function ( frame )
if not frame:getParent() then
error( '{{#invoke:Unsubst|}} makes no sense without a parent frame' )
end
if not frame.args['$B'] then
error( '{{#invoke:Unsubst|}} requires parameter $B (template content)' )
end
if mw.isSubsting() then
---- substing
-- Combine passed args with passed defaults
local args = {}
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'Y年n月' )
end
args[k] = v
end
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
-- Build an equivalent template invocation
-- First, find the title to use
local titleobj = mw.title.new(frame:getParent():getTitle())
local title
if titleobj.namespace == 10 then -- NS_TEMPLATE
title = titleobj.text
elseif titleobj.namespace == 0 then -- NS_MAIN
title = ':' .. titleobj.text
else
title = titleobj.prefixedText
end
-- Build the invocation body with numbered args first, then named
local ret = '{{' .. title
for k, v in ipairs( args ) do
if string.find( v, '=', 1, true ) then
-- likely something like 1=foo=bar, we need to do it as a named arg
break
end
ret = ret .. '|' .. v
args[k] = nil
end
for k, v in pairs( args ) do
ret = ret .. '|' .. k .. '=' .. v
end
return ret .. '}}'
else
---- Not substing
-- Just return the "body"
return frame.args['$B'] .. (frame.args['$N'] and frame:getParent():getTitle() == mw.title.getCurrentTitle().prefixedText and '[[Category:使用$N的Module:Unsubst调用]]' or '')
end
end
return p
e8abf58ec4f76139537c53e4f6005c233e38d6d8
Module:Category handler
828
60
114
2017-10-12T08:30:03Z
zhwp>Xiplus
0
已保护“[[模块:Category handler]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- CATEGORY HANDLER --
-- --
-- This module implements the {{category handler}} template in Lua, --
-- with a few improvements: all namespaces and all namespace aliases --
-- are supported, and namespace names are detected automatically for --
-- the local wiki. This module requires [[Module:Namespace detect]] --
-- and [[Module:Yesno]] to be available on the local wiki. It can be --
-- configured for different wikis by altering the values in --
-- [[Module:Category handler/config]], and pages can be blacklisted --
-- from categorisation by using [[Module:Category handler/blacklist]]. --
-- --
--------------------------------------------------------------------------------
-- Load required modules
local yesno = require('Module:Yesno')
-- Lazily load things we don't always need
local mShared, mappings
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function trimWhitespace(s, removeBlanks)
if type(s) ~= 'string' then
return s
end
s = s:match('^%s*(.-)%s*$')
if removeBlanks then
if s ~= '' then
return s
else
return nil
end
else
return s
end
end
--------------------------------------------------------------------------------
-- CategoryHandler class
--------------------------------------------------------------------------------
local CategoryHandler = {}
CategoryHandler.__index = CategoryHandler
function CategoryHandler.new(data, args)
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
-- Set the title object
do
local pagename = obj:parameter('demopage')
local success, titleObj
if pagename then
success, titleObj = pcall(mw.title.new, pagename)
end
if success and titleObj then
obj.title = titleObj
if titleObj == mw.title.getCurrentTitle() then
obj._usesCurrentTitle = true
end
else
obj.title = mw.title.getCurrentTitle()
obj._usesCurrentTitle = true
end
end
-- Set suppression parameter values
for _, key in ipairs{'nocat', 'categories'} do
local value = obj:parameter(key)
value = trimWhitespace(value, true)
obj['_' .. key] = yesno(value)
end
do
local subpage = obj:parameter('subpage')
local category2 = obj:parameter('category2')
if type(subpage) == 'string' then
subpage = mw.ustring.lower(subpage)
end
if type(category2) == 'string' then
subpage = mw.ustring.lower(category2)
end
obj._subpage = trimWhitespace(subpage, true)
obj._category2 = trimWhitespace(category2) -- don't remove blank values
end
return obj
end
function CategoryHandler:parameter(key)
local parameterNames = self._data.parameters[key]
local pntype = type(parameterNames)
if pntype == 'string' or pntype == 'number' then
return self._args[parameterNames]
elseif pntype == 'table' then
for _, name in ipairs(parameterNames) do
local value = self._args[name]
if value ~= nil then
return value
end
end
return nil
else
error(string.format(
'invalid config key "%s"',
tostring(key)
), 2)
end
end
function CategoryHandler:isSuppressedByArguments()
return
-- See if a category suppression argument has been set.
self._nocat == true
or self._categories == false
or (
self._category2
and self._category2 ~= self._data.category2Yes
and self._category2 ~= self._data.category2Negative
)
-- Check whether we are on a subpage, and see if categories are
-- suppressed based on our subpage status.
or self._subpage == self._data.subpageNo and self.title.isSubpage
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
end
function CategoryHandler:shouldSkipBlacklistCheck()
-- Check whether the category suppression arguments indicate we
-- should skip the blacklist check.
return self._nocat == false
or self._categories == true
or self._category2 == self._data.category2Yes
end
function CategoryHandler:matchesBlacklist()
if self._usesCurrentTitle then
return self._data.currentTitleMatchesBlacklist
else
mShared = mShared or require('Module:Category handler/shared')
return mShared.matchesBlacklist(
self.title.prefixedText,
mw.loadData('Module:Category handler/blacklist')
)
end
end
function CategoryHandler:isSuppressed()
-- Find if categories are suppressed by either the arguments or by
-- matching the blacklist.
return self:isSuppressedByArguments()
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
end
function CategoryHandler:getNamespaceParameters()
if self._usesCurrentTitle then
return self._data.currentTitleNamespaceParameters
else
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
return mShared.getNamespaceParameters(
self.title,
mappings
)
end
end
function CategoryHandler:namespaceParametersExist()
-- Find whether any namespace parameters have been specified.
-- We use the order "all" --> namespace params --> "other" as this is what
-- the old template did.
if self:parameter('all') then
return true
end
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
for ns, params in pairs(mappings) do
for i, param in ipairs(params) do
if self._args[param] then
return true
end
end
end
if self:parameter('other') then
return true
end
return false
end
function CategoryHandler:getCategories()
local params = self:getNamespaceParameters()
local nsCategory
for i, param in ipairs(params) do
local value = self._args[param]
if value ~= nil then
nsCategory = value
break
end
end
if nsCategory ~= nil or self:namespaceParametersExist() then
-- Namespace parameters exist - advanced usage.
if nsCategory == nil then
nsCategory = self:parameter('other')
end
local ret = {self:parameter('all')}
local numParam = tonumber(nsCategory)
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
-- nsCategory is an integer
ret[#ret + 1] = self._args[numParam]
else
ret[#ret + 1] = nsCategory
end
if #ret < 1 then
return nil
else
return table.concat(ret)
end
elseif self._data.defaultNamespaces[self.title.namespace] then
-- Namespace parameters don't exist, simple usage.
return self._args[1]
end
return nil
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- Used for testing purposes.
return {
CategoryHandler = CategoryHandler
}
end
function p._main(args, data)
data = data or mw.loadData('Module:Category handler/data')
local handler = CategoryHandler.new(data, args)
if handler:isSuppressed() then
return nil
end
return handler:getCategories()
end
function p.main(frame, data)
data = data or mw.loadData('Module:Category handler/data')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = data.wrappers,
valueFunc = function (k, v)
v = trimWhitespace(v)
if type(k) == 'number' then
if v ~= '' then
return v
else
return nil
end
else
return v
end
end
})
return p._main(args, data)
end
return p
b74dd63857b24904ac452429b11213f18647471f
Module:Category handler/blacklist
828
67
128
2017-10-12T08:30:11Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/blacklist]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^那艺娜维基:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^那艺娜维基:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
939eea9afe7dd0de8be68d71a9cbccfca2c3d6ee
242
128
2017-10-12T08:30:11Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/blacklist]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^那艺娜维基:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^那艺娜维基:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
939eea9afe7dd0de8be68d71a9cbccfca2c3d6ee
350
242
2017-10-12T08:30:11Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/blacklist]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^Wikipedia:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^Wikipedia:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
c84948ad9808d5d323408d5d10d5652f748a0550
Module:Category handler/config
828
65
124
2017-10-12T08:30:17Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/config]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--------------------------------------------------------------------------------
-- [[Module:Category handler]] configuration data --
-- Language-specific parameter names and values can be set here. --
-- For blacklist config, see [[Module:Category handler/blacklist]]. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- foo = 'parameter name', --
-- --
-- To add multiple names, you can use this format: --
-- --
-- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, --
--------------------------------------------------------------------------------
cfg.parameters = {
-- The nocat and categories parameter suppress
-- categorisation. They are used with Module:Yesno, and work as follows:
--
-- cfg.nocat:
-- Result of yesno() Effect
-- true Categorisation is suppressed
-- false Categorisation is allowed, and
-- the blacklist check is skipped
-- nil Categorisation is allowed
--
-- cfg.categories:
-- Result of yesno() Effect
-- true Categorisation is allowed, and
-- the blacklist check is skipped
-- false Categorisation is suppressed
-- nil Categorisation is allowed
nocat = 'nocat',
categories = 'categories',
-- The parameter name for the legacy "category2" parameter. This skips the
-- blacklist if set to the cfg.category2Yes value, and suppresses
-- categorisation if present but equal to anything other than
-- cfg.category2Yes or cfg.category2Negative.
category2 = 'category2',
-- cfg.subpage is the parameter name to specify how to behave on subpages.
subpage = 'subpage',
-- The parameter for data to return in all namespaces.
all = 'all',
-- The parameter name for data to return if no data is specified for the
-- namespace that is detected.
other = 'other',
-- The parameter name used to specify a page other than the current page;
-- used for testing and demonstration.
demopage = 'page',
}
--------------------------------------------------------------------------------
-- Parameter values --
-- These are set values that can be used with certain parameters. Only one --
-- value can be specified, like this: --
-- --
-- cfg.foo = 'value name' -- --
--------------------------------------------------------------------------------
-- The following settings are used with the cfg.category2 parameter. Setting
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2
-- is present but equal to anything other than cfg.category2Yes or
-- cfg.category2Negative then it supresses cateogrisation.
cfg.category2Yes = 'yes'
cfg.category2Negative = '¬'
-- The following settings are used with the cfg.subpage parameter.
-- cfg.subpageNo is the value to specify to not categorise on subpages;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.
cfg.subpageNo = 'no'
cfg.subpageOnly = 'only'
--------------------------------------------------------------------------------
-- Default namespaces --
-- This is a table of namespaces to categorise by default. The keys are the --
-- namespace numbers. --
--------------------------------------------------------------------------------
cfg.defaultNamespaces = {
[ 0] = true, -- main
[ 6] = true, -- file
[ 12] = true, -- help
[ 14] = true, -- category
[100] = true, -- portal
[108] = true, -- book
}
--------------------------------------------------------------------------------
-- Wrappers --
-- This is a wrapper template or a list of wrapper templates to be passed to --
-- [[Module:Arguments]]. --
--------------------------------------------------------------------------------
cfg.wrappers = 'Template:Category handler'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
373cd107b13a5b00e6a1b7e66a749f12502c849d
Module:Category handler/data
828
64
122
2017-10-12T08:30:24Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/data]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module assembles data to be passed to [[Module:Category handler]] using
-- mw.loadData. This includes the configuration data and whether the current
-- page matches the title blacklist.
local data = require('Module:Category handler/config')
local mShared = require('Module:Category handler/shared')
local blacklist = require('Module:Category handler/blacklist')
local title = mw.title.getCurrentTitle()
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(
title.prefixedText,
blacklist
)
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(
title,
mShared.getParamMappings()
)
return data
abbc68048ff698e88dda06b64ecf384bbf583120
Module:Category handler/shared
828
66
126
2017-10-12T08:30:30Z
zhwp>Xiplus
0
已保护“[[模块:Category handler/shared]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module contains shared functions used by [[Module:Category handler]]
-- and its submodules.
local p = {}
function p.matchesBlacklist(page, blacklist)
for i, pattern in ipairs(blacklist) do
local match = mw.ustring.match(page, pattern)
if match then
return true
end
end
return false
end
function p.getParamMappings(useLoadData)
local dataPage = 'Module:Namespace detect/data'
if useLoadData then
return mw.loadData(dataPage).mappings
else
return require(dataPage).mappings
end
end
function p.getNamespaceParameters(titleObj, mappings)
-- We don't use title.nsText for the namespace name because it adds
-- underscores.
local mappingsKey
if titleObj.isTalkPage then
mappingsKey = 'talk'
else
mappingsKey = mw.site.namespaces[titleObj.namespace].name
end
mappingsKey = mw.ustring.lower(mappingsKey)
return mappings[mappingsKey] or {}
end
return p
d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5
Template:Link-en
10
308
641
2017-10-21T11:12:25Z
zhwp>Xiplus
0
已保护“[[Template:Link-en]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/en]]
{{短名重定向}}
{{模板重定向}}
866c4d05848633090eb9763d9c480ebe2c6b4fdf
Template:缺乏中文說明
10
280
584
2018-01-27T18:19:30Z
zhwp>Tang891228
0
添加{{[[T:Documentation|Documentation]]}}
wikitext
text/x-wiki
{{缺乏使用說明|中文=是}}<noinclude>{{Documentation}}[[Category:模板页的模板]]</noinclude>
4701f009a3627981bfadd1e70c2ec749724b8c65
Template:Trim
10
249
515
2018-01-30T02:08:07Z
zhwp>Xiplus
0
已更改“[[Template:Trim]]”的保护等级:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{ {{{|safesubst:}}}#if:1|{{{1|}}}}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
80cbf249bdbb60b46ba41f0d928c8f463c62983e
Template:When on basepage
10
272
566
2018-03-31T11:48:45Z
zhwp>Xiplus
0
已保护“[[Template:When on basepage]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "page" parameter then detect
basepage/subpage/subsubpage-->
{{#if:{{{page|}}}
| {{#if:{{#titleparts:{{{page}}}|0|3}}
| subsubpage <!--Subsubpage or lower-->
| {{#if:{{#titleparts:{{{page}}}|0|2}}
| subpage
| basepage
}}
}}
| {{#if:{{#titleparts:{{FULLPAGENAME}}|0|3}}
| subsubpage <!--Subsubpage or lower-->
| {{#if:{{#titleparts:{{FULLPAGENAME}}|0|2}}
| subpage
| basepage
}}
}}
}}
| basepage = {{{1|}}}
| subpage = {{{2|}}}
| subsubpage = {{{3| {{{2|}}} }}} <!--Respecting empty parameter on purpose-->
}}<!--End switch--><noinclude>
{{Documentation}}
</noinclude>
cf4dc92df647a26ab0ce149772a1fe3ac6c3dfc0
Template:Dummy ref
10
202
422
2018-04-21T17:39:39Z
zhwp>JC1
0
Justincheng12345 已移動頁面 [[Template:Dummy ref]] 至 [[Template:Dummy reference]]
wikitext
text/x-wiki
#重定向 [[Template:Dummy reference]]
46141c3444bc34175c04cdf7f5271ca92bcb2a8e
Module:WikitextLC
828
127
250
2018-04-30T03:30:34Z
zhwp>Bluedeck
0
EP
Scribunto
text/plain
local p = {}
--- Construct an inline conversion from a table input.
-- @param content table of the form
-- { ["zh-cn"]='foobar', ["zh-tw"]='firecat', ["zh-hk"]='' }
-- @returns string
-- "-{zh-cn:foobar;zh-tw:firecat;zh-hk:<span></span>}-"
--
-- @fixme allow for generating output without "-{" "}-", so that
-- it can be used with the last three wrappers.
function p.selective( content )
local text = '-{'
for variant, value in pairs( content ) do
if value == '' then
value = '<span></span>'
end
text = text .. variant .. ':' .. value .. ';'
end
text = text .. '}-'
return text
end
--- Write some text with a limited set of variants to convert to
--
-- @param content text to be written
-- @param variant a variant (string), or a list of variants
-- (semicolon-deliminated string, or table of strings)
-- @param[opt] force convert even under "zh" (no conversion) locale
function p.converted( content, variant, force )
if type( variant ) == 'table' then
variant = table.concat( variant, ';' )
end
return '-{' .. ( force and '' or 'zh;' ) .. variant .. '|' .. content .. '}-'
end
--- Wraps some "raw text" to not convert.
--
-- @fixme Is the "R" flag some undocumented/undefined no-op magic?
-- Are we using it instead of the old '-{' .. content .. '}-'
-- to avoid confusion caused by a flag in the "content"?
function p.raw( content )
return '-{R|' .. content .. '}-'
end
--- Wraps a title conversion rule.
function p.title( content )
return '-{T|' .. content .. '}-'
end
--- Wraps a (hidden) conversion rule definition.
function p.hidden( content )
return '-{H|' .. content .. '}-'
end
return p
76127574463fdd2329adddcc73f9a0f6b1aa12ea
Module:Separated entries
828
71
136
2018-07-09T03:06:09Z
zhwp>Xiplus
0
已保护“[[模块:Separated entries]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
-- This module takes positional parameters as input and concatenates them with
-- an optional separator. The final separator (the "conjunction") can be
-- specified independently, enabling natural-language lists like
-- "foo, bar, baz and qux".
local compressSparseArray = require('Module:TableTools').compressSparseArray
local p = {}
function p._main(args)
local separator = args.separator
-- Decode (convert to Unicode) HTML escape sequences, such as " " for space.
and mw.text.decode(args.separator) or ''
local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator
-- Discard named parameters.
local values = compressSparseArray(args)
return mw.text.listToText(values, separator, conjunction)
end
local function makeInvokeFunction(separator, conjunction)
return function (frame)
local args = require('Module:Arguments').getArgs(frame)
args.separator = separator or args.separator
args.conjunction = conjunction or args.conjunction
return p._main(args)
end
end
p.main = makeInvokeFunction()
p.br = makeInvokeFunction('<br />')
p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain())
return p
b8d9de70633108b00f860aed20a52b749fdeca15
Template:Br separated entries
10
215
448
2018-07-09T03:09:10Z
zhwp>Xiplus
0
已保护“[[Template:Br separated entries]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Separated entries|br}}<noinclude>
{{documentation}}
</noinclude>
2019f7fc383259e70d66e43cbd97a43d20889f1b
Template:MONTHNAME
10
230
479
2018-07-09T03:10:06Z
zhwp>Xiplus
0
已保护“[[Template:MONTHNAME]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{#if:{{{1|}}}|{{#switch:{{MONTHNUMBER|{{{1}}}}}|1=1月|2=2月|3=3月|4=4月|5=5月|6=6月|7=7月|8=8月|9=9月|10=10月|11=11月|12=12月|Incorrect required parameter 1=''month''!}}|Missing required parameter 1=''month''!}}</includeonly><noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
1589efdb31d554291283e4aa24741ab640a30ef0
Template:Basepage subpage
10
271
564
2018-07-09T03:10:31Z
zhwp>Xiplus
0
已保护“[[Template:Basepage subpage]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
#重定向 [[Template:When on basepage]]
89cca1422cd3731b93eaaf5aadbe96cee6f121ff
Template:Nowrap
10
125
246
2018-12-03T08:52:03Z
zhwp>Jimmy Xu
0
ep
wikitext
text/x-wiki
<includeonly><span class="nowrap">{{{1}}}</span></includeonly><noinclude>{{Documentation}}</noinclude>
6d6bcfa036745c59ef032b1eeed975bfb4a3d395
Template:Fake heading
10
193
404
2018-12-06T18:30:42Z
zhwp>Great Brightstar
0
wikitext
text/x-wiki
<templatestyles src="Fake heading/styles.css"/><div class="fakeHeading {{#switch: {{{level|{{{sub|}}}}}}
| 1 = h1
| 2 | #default = h2
| 3 = h3
| 4 = h4
| 5 = h5
| 6 = h6
}}">{{{1|分段}}}</div><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
57b618039321d9c272af2f821696f88e30de9ae7
MediaWiki:Gadget-Twinkle
8
149
300
2019-01-14T02:35:00Z
zhwp>Jimmy Xu
0
wikitext
text/x-wiki
[[WP:Twinkle|Twinkle]] <small>自动进行常见维护操作([[Wikipedia:Twinkle/参数设置|参数设置]])</small>
1c63a1a4c1c4467c0f7529cad174701ea722b434
Template:NoteTA
10
124
244
2019-01-15T17:27:44Z
zhwp>Iokseng
0
Iokseng 已移動頁面 [[Template:NoteTA/lua]] 至 [[Template:NoteTA]],不留重新導向
wikitext
text/x-wiki
{{#invoke:NoteTA|main}}<noinclude>
{{模板文档}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
866263768f3a626ea5c1d5bebbbb17c9ce57983c
Template:高風險模板
10
283
590
2019-01-25T02:00:54Z
zhwp>SunAfterRain
0
[[WP:AES|←]]重定向到[[Template:High-use]]
wikitext
text/x-wiki
#重定向[[Template:High-use]]
2addfe7d74d1f617ed20992212229200d0866fd6
Template:High-risk
10
118
230
2019-02-20T11:19:33Z
zhwp>Xiplus
0
[[WP:AES|←]]页面内容被替换为:'#redirect [[Template:High-use]]'
wikitext
text/x-wiki
#redirect [[Template:High-use]]
e3ccadb5eecb45781d9058d6bea86c3f38f278d1
Module:Crc32lua
828
129
254
2019-02-26T15:10:54Z
zhwp>Xiplus
0
已保护“[[模块:Crc32lua]]”:高风险模板([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
Scribunto
text/plain
--[[
LUA MODULE
digest.crc32 - CRC-32 checksum implemented entirely in Lua.
SYNOPSIS
local CRC = require 'digest.crc32lua'
print(CRC.crc32 'test') --> 0xD87F7E0C or -662733300
assert(CRC.crc32('st', CRC.crc32('te')) == CRC.crc32 'test')
DESCRIPTION
This can be used to compute CRC-32 checksums on strings.
This is similar to [1-2].
API
Note: in the functions below, checksums are 32-bit integers stored in
numbers. The number format currently depends on the bit
implementation--see DESIGN NOTES below.
CRC.crc32_byte(byte [, crc]) --> rcrc
Returns CRC-32 checksum `rcrc` of byte `byte` (number 0..255) appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32_string(s, crc) --> bcrc
Returns CRC-32 checksum `rcrc` of string `s` appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32(o, crc) --> bcrc
This invokes `crc32_byte` if `o` is a byte or `crc32_string` if `o`
is a string.
CRC.bit
This contains the underlying bit library used by the module. It
should be considered a read-only copy.
DESIGN NOTES
Currently, this module exposes the underlying bit array implementation in CRC
checksums returned. In BitOp, bit arrays are 32-bit signed integer numbers
(may be negative). In Lua 5.2 'bit32' and 'bit.numberlua', bit arrays are
32-bit unsigned integer numbers (non-negative). This is subject to change
in the future but is currently done due to (unconfirmed) performance
implications.
On platforms with 64-bit numbers, one way to normalize CRC
checksums to be unsigned is to do `crcvalue % 2^32`,
The name of this module is inspired by Perl `Digest::CRC*`.
DEPENDENCIES
Requires one of the following bit libraries:
BitOp "bit" -- bitop.luajit.org -- This is included in LuaJIT and also available
for Lua 5.1/5.2. This provides the fastest performance in LuaJIT.
Lua 5.2 "bit32" -- www.lua.org/manual/5.2 -- This is provided in Lua 5.2
and is preferred in 5.2 (unless "bit" also happens to be installed).
"bit.numberlua" (>=000.003) -- https://github.com/davidm/lua-bit-numberlua
This is slowest and used as a last resort.
It is only a few times slower than "bit32" though.
DOWNLOAD/INSTALLATION
If using LuaRocks:
luarocks install lua-digest-crc32lua
Otherwise, download <https://github.com/davidm/lua-digest-crc32lua/zipball/master>.
Alternately, if using git:
git clone git://github.com/davidm/lua-digest-crc32lua.git
cd lua-digest-crc32lua
Optionally unpack:
./util.mk
or unpack and install in LuaRocks:
./util.mk install
REFERENCES
[1] http://www.axlradius.com/freestuff/CRC32.java
[2] http://www.gamedev.net/reference/articles/article1941.asp
[3] http://java.sun.com/j2se/1.5.0/docs/api/java/util/zip/CRC32.html
[4] http://www.dsource.org/projects/tango/docs/current/tango.io.digest.Crc32.html
[5] http://pydoc.org/1.5.2/zlib.html#-crc32
[6] http://www.python.org/doc/2.5.2/lib/module-binascii.html
LICENSE
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
(end license)
--]]
local M = {_TYPE='module', _NAME='digest.crc32', _VERSION='0.3.20111128'}
local type = type
local require = require
local setmetatable = setmetatable
--[[
Requires the first module listed that exists, else raises like `require`.
If a non-string is encountered, it is returned.
Second return value is module name loaded (or '').
--]]
local function requireany(...)
local errs = {}
for _,name in ipairs{...} do
if type(name) ~= 'string' then return name, '' end
local ok, mod = pcall(require, name)
if ok then return mod, name end
errs[#errs+1] = mod
end
error(table.concat(errs, '\n'), 2)
end
local bit, name_ = requireany('bit32', 'bit', 'bit.numberlua')
local bxor = bit.bxor
local bnot = bit.bnot
local band = bit.band
local rshift = bit.rshift
-- CRC-32-IEEE 802.3 (V.42)
local POLY = 0xEDB88320
-- Memoize function pattern (like http://lua-users.org/wiki/FuncTables ).
local function memoize(f)
local mt = {}
local t = setmetatable({}, mt)
function mt:__index(k)
local v = f(k); t[k] = v
return v
end
return t
end
-- CRC table.
local crc_table = memoize(function(i)
local crc = i
for _=1,8 do
local b = band(crc, 1)
crc = rshift(crc, 1)
if b == 1 then crc = bxor(crc, POLY) end
end
return crc
end)
function M.crc32_byte(byte, crc)
crc = bnot(crc or 0)
local v1 = rshift(crc, 8)
local v2 = crc_table[bxor(crc % 256, byte)]
return bnot(bxor(v1, v2))
end
local M_crc32_byte = M.crc32_byte
function M.crc32_string(s, crc)
crc = crc or 0
for i=1,#s do
crc = M_crc32_byte(s:byte(i), crc)
end
return crc
end
local M_crc32_string = M.crc32_string
function M.crc32(s, crc)
if type(s) == 'string' then
return M_crc32_string(s, crc)
else
return M_crc32_byte(s, crc)
end
end
M.bit = bit -- bit library used
return M
516bb70cd6815ac4a27c60f6bd63a90d26581f95
Module:No globals
828
63
120
2019-05-26T02:06:31Z
zhwp>Antigng
0
ep:修正错误翻译
Scribunto
text/plain
local mt = getmetatable(_G) or {}
function mt.__index (t, k)
if k ~= 'arg' then
error('尝试读取空全局变量:' .. tostring(k), 2)
end
return nil
end
function mt.__newindex(t, k, v)
if k ~= 'arg' then
error('尝试写入全局变量:' .. tostring(k), 2)
end
rawset(t, k, v)
end
setmetatable(_G, mt)
75f542ec50e6eec7c23271b53c09f1c648b88f77
Module:Demo
828
139
286
2019-06-05T08:31:35Z
zhwp>Qqkuro66541
0
Scribunto
text/plain
local p = {}
--creates a frame object that cannot access any of the parent's args
--unless a table containing a list keys of not to inherit is provided
function disinherit(frame, onlyTheseKeys)
local parent = frame:getParent() or frame
local orphan = parent:newChild{}
orphan.getParent = parent.getParent --returns nil
orphan.args = {}
if onlyTheseKeys then
local family = {parent, frame}
for f = 1, 2 do
for k, v in pairs(family[f] and family[f].args or {}) do
orphan.args[k] = orphan.args[k] or v
end
end
parent.args = mw.clone(orphan.args)
setmetatable(orphan.args, nil)
for _, k in ipairs(onlyTheseKeys) do
rawset(orphan.args, k, nil)
end
end
return orphan, parent
end
function p.get(frame, arg, passArgs)
local orphan, frame = disinherit(frame, passArgs and {arg or 1})
local code, noWiki, preserve = frame.args[arg or 1] or ''
if code:match'nowiki' then
local placeholder, preserve = ('6'):char(), {}
code = mw.text.unstripNoWiki(code)
noWiki = code:gsub('%%', placeholder):gsub('<', '<'):gsub('>', '>')
for k in noWiki:gmatch('&.-;') do
if not preserve[k] then
preserve[k] = true
table.insert(preserve, (k:gsub('&', '&')))
noWiki = noWiki:gsub('(&.-;)', '%%%s')
end
end
noWiki = mw.text.nowiki(noWiki):format(unpack(preserve)):gsub(placeholder, '%%')
end
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
return {
source = noWiki or code,
output = orphan:preprocess(code):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
}
end
function p.main(frame, demoTable)
local show = demoTable or p.get(frame)
local args = show.frame.args
args.br = tonumber(args.br or 1) and ('<br>'):rep(args.br or 1) or args.br or ''
if show[args.result_arg] then
return show[args.result_arg]
end
return string.format('<pre%s>%s</pre>%s%s', args.style and string.format(" style='%s'", args.style) or '', show.source, args.br, show.output)
end
-- Alternate function to return an inline result
function p.inline(frame, demoTable)
local show = demoTable or p.get(frame)
local args = show.frame.args
if show[args.result_arg] then
return show[args.result_arg]
end
return string.format('<code%s>%s</code>%s%s', args.style and string.format(" style='%s'", args.style) or '', show.source, ' → ', show.output)
end
--passing of args into other module without preprocessing
function p.module(frame)
local orphan, frame = disinherit(frame, {
'demo_template',
'demo_module',
'demo_module_func',
'demo_main',
'demo_br',
'demo_result_arg',
'demo_kill_categories',
'nocat'
})
local template = frame.args.demo_template and 'Template:'..frame.args.demo_template
local demoFunc = frame.args.demo_module_func or 'main\n'
local demoModule = require('Module:' .. frame.args.demo_module)[demoFunc:match('^%s*(.-)%s*$')]
frame.args.br, frame.args.result_arg = frame.args.demo_br, frame.args.demo_result_arg
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
if demoModule then
local named = {insert = function(self, ...) table.insert(self, ...) return self end}
local source = {insert = named.insert, '{{', frame.args.demo_template or frame.args.demo_module, '\n'}
if not template then
source:insert(2, '#invoke:'):insert(4, '|'):insert(5, demoFunc)
end
local insertNamed = #source + 1
for k, v in pairs(orphan.args) do
local nan, insert = type(k) ~= 'number', {v}
local target = nan and named or source
target:insert'|'
if nan then
target:insert(k):insert'=':insert'\n'
table.insert(insert, 1, #target)
end
target:insert(unpack(insert))
local nowiki = v:match('nowiki')
if nowiki or v:match('{{.-}}') then
orphan.args[k] = frame:preprocess(nowiki and mw.text.unstripNoWiki(v) or v)
end
end
source:insert'}}'
table.insert(source, insertNamed, table.concat(named))
return p.main(orphan, {
source = mw.text.encode(table.concat(source), "<>'|=~"),
output = tostring(demoModule(orphan)):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
})
else
return "ERROR: Invalid module function: "..demoFunc
end
end
return p
021b3b6a2d34baf26bbf17d89e1c22a2d1db6a11
Template:Category handler/numbered
10
266
554
2019-06-14T01:28:38Z
zhwp>Xiplus
0
已保护“[[Template:Category handler/numbered]]”:高风险模板:47萬引用([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
{{#iferror: {{#expr: 1 + {{{data|}}} }}
| {{{data|}}} <!--Not a number, return "data" as is-->
| {{{ {{{data|}}} |}}} <!--"data" is a number, return that numbered parameter-->
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
48d906542dfe053be2e00190637ed322717506f9
Module:Hatnote
828
76
146
2019-06-25T09:47:37Z
zhwp>Xiplus
0
per [[Special:PermaLink/54755035#更补一些本地化内容|EP]] 自[[模块:Hatnote/sandbox]]合并[[Special:Contributions/Viztor|Viztor]]的[[Special:PermaLink/54755032|版本54755032]]
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote --
-- --
-- This module produces hatnote links and links to related articles. It --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules. --
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
function p.findNamespaceId(link, removeColon)
-- Finds the namespace id (namespace number) of a link or a pagename. This
-- function will not work if the link is enclosed in double brackets. Colons
-- are trimmed from the start of the link by default. To skip colon
-- trimming, set the removeColon parameter to false.
checkType('findNamespaceId', 1, link, 'string')
checkType('findNamespaceId', 2, removeColon, 'boolean', true)
if removeColon ~= false then
link = removeInitialColon(link)
end
local namespace = link:match('^(.-):')
if namespace then
local nsTable = mw.site.namespaces[namespace]
if nsTable then
return nsTable.id
end
end
return 0
end
function p.formatPages(...)
-- Formats a list of pages using formatLink and returns it as an array. Nil
-- values are not allowed.
local pages = {...}
local ret = {}
for i, page in ipairs(pages) do
ret[i] = p._formatLink(page)
end
return ret
end
function p.formatPageTables(...)
-- Takes a list of page/display tables and returns it as a list of
-- formatted links. Nil values are not allowed.
local pages = {...}
local links = {}
for i, t in ipairs(pages) do
checkType('formatPageTables', i, t, 'table')
local link = t[1]
local display = t[2]
links[i] = p._formatLink(link, display)
end
return links
end
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
-- is added.
checkType('makeWikitextError', 1, msg, 'string')
checkType('makeWikitextError', 2, helpLink, 'string', true)
yesno = require('Module:Yesno')
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
local helpText
if helpLink then
helpText = '([[' .. helpLink .. '|帮助]])'
else
helpText = ''
end
-- Make the category text.
local category
if not title.isTalkPage and yesno(addTrackingCategory) ~= false then
category = '有错误的顶注模板'
category = string.format(
'[[%s:%s]]',
mw.site.namespaces[14].name,
category
)
else
category = ''
end
return string.format(
'<strong class="error">错误:%s%s。</strong>%s',
msg,
helpText,
category
)
end
function p.disambiguate(page, disambiguator)
-- Formats a page title with a disambiguation parenthetical,
-- i.e. "Example" → "Example (disambiguation)".
checkType('disambiguate', 1, page, 'string')
checkType('disambiguate', 2, disambiguator, 'string', true)
disambiguator = disambiguator or '消歧义'
return string.format('%s (%s)', page, disambiguator)
end
--------------------------------------------------------------------------------
-- Format link 格式化链接
--
-- Makes a wikilink from the given link and display values. Links are escaped
-- with colons if necessary, and links to sections are detected and displayed
-- with " § " as a separator rather than the standard MediaWiki "#". Used in
-- the {{format hatnote link}} template.
--------------------------------------------------------------------------------
function p.formatLink(frame)
local args = getArgs(frame)
local link = args[1]
local display = args[2]
if not link then
return p.makeWikitextError(
'link参数缺失',
'Template:Format hatnote link#错误',
args.category
)
end
return p._formatLink(link, display)
end
function p._formatLink(link, display)
checkType('_formatLink', 1, link, 'string')
checkType('_formatLink', 2, display, 'string', true)
-- ignore transwiki link
if link:match('<span class="ilh-') then
return link
end
-- Remove the initial colon for links where it was specified manually.
link = removeInitialColon(link)
-- Find whether a faux display value has been added with the {{!}} magic
-- word.
if not display then
local prePipe, postPipe = link:match('^(.-)|(.*)$')
link = prePipe or link
display = postPipe
end
-- Find the display value.
if not display then
local page, section = link:match('^(.-)#(.*)$')
if page then
display = page .. ' § ' .. section
end
end
-- Assemble the link.
if display then
return string.format(
'[[:%s|%s]]',
string.gsub(link, '|(.*)$', ''), --display overwrites manual piping
display
)
else
return string.format('[[:%s]]', link)
end
end
--------------------------------------------------------------------------------
-- Hatnote 顶注
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
-- 产生标准顶注文字。实现{{hatnote}}模板
--------------------------------------------------------------------------------
function p.hatnote(frame)
local args = getArgs(frame)
local s = args[1]
local options = {}
if not s then
return p.makeWikitextError(
'text参数缺失',
'Template:Hatnote#错误',
args.category
)
end
options.extraclasses = args.extraclasses
options.selfref = args.selfref
return p._hatnote(s, options)
end
function p._hatnote(s, options)
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 2, options, 'table', true)
options = options or {}
local classes = {'hatnote', 'navigation-not-searchable'}
local extraclasses = options.extraclasses
local selfref = options.selfref
if type(extraclasses) == 'string' then
classes[#classes + 1] = extraclasses
end
if selfref then
classes[#classes + 1] = 'selfref'
end
return string.format(
'<div role="note" class="%s">%s</div>',
table.concat(classes, ' '),
s
)
end
return p
adada2183763348aa1d17e8e24a47b05f39eb28c
Template:Tlc
10
77
148
2019-08-18T06:13:42Z
zhwp>SunAfterRain
0
wikitext
text/x-wiki
<code style="white-space:nowrap;">-{}-{{{{#if:{{{1|}}}|{{{1}}}|tlc|...}}<!--
-->{{#ifeq:{{{2|x}}}|{{{2|}}}| |{{{2}}} | }}<!--
-->{{#ifeq:{{{3|x}}}|{{{3|}}}| |{{{3}}} | }}<!--
-->{{#ifeq:{{{4|x}}}|{{{4|}}}| |{{{4}}} | }}<!--
-->{{#ifeq:{{{5|x}}}|{{{5|}}}| |{{{5}}} | }}<!--
-->{{#ifeq:{{{6|x}}}|{{{6|}}}| |{{{6}}} | }}<!--
-->{{#ifeq:{{{7|x}}}|{{{7|}}}| |{{{7}}} | }}<!--
-->{{#ifeq:{{{8|x}}}|{{{8|}}}| |{{{8}}} | }}<!--
-->{{#ifeq:{{{9|x}}}|{{{9|}}}| |{{{9}}} | }}<!--
-->}}</code><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
db08bcc30fc73d9872756d0cde1c147fbfa4250a
那艺娜维基:請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。
4
21
37
2019-09-15T05:12:43Z
zhwp>Lopullinen
0
([[:w:zh:User:镜音铃/Wikiplus|W+]])
wikitext
text/x-wiki
#REDIRECT [[Template:Sandbox heading]]
623db2a6ae7dc15c833cef604ced75a5c2e01189
Template:請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。
10
49
91
2019-09-15T05:12:43Z
zhwp>Lopullinen
0
([[:w:zh:User:镜音铃/Wikiplus|W+]])
wikitext
text/x-wiki
#REDIRECT [[Template:Sandbox heading]]
623db2a6ae7dc15c833cef604ced75a5c2e01189
User:Emojiwiki/username
2
324
673
2020-02-08T02:35:04Z
zhwp>Emojiwiki
0
[[WP:UNDO|撤销]][[Special:Contributions/Emojiwiki|Emojiwiki]]([[User talk:Emojiwiki|讨论]])的版本58040214
wikitext
text/x-wiki
<span style="font-weight:bold;font-family:'Microsoft Yahei';"><span style="color:#003366">E</span><span style="color:#003399">m</span><span style="color:#000066">o</span><span style="color:#6600cc">j</span><span style="color:#660066">i</span><span style="color:#993366">w</span><span style="color:#993333">i</span><span style="color:#993300">k</span><span style="color:#663300">i</span></span>
991ba7070c6754da451133094108944c2bdc1d19
Template:ISO 639 name
10
260
542
2020-02-14T03:56:36Z
zhwp>Xiplus
0
已保护“[[Template:ISO 639 name]]”:高風險模板:273022引用([编辑=仅管理员](无限期)[移动=仅管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{ISO 639 name {{{1|undefined}}}}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
5a97bd834fc99f9308b9143563978662c4387811
User:Emojiwiki/module/title
2
325
675
2020-02-21T09:49:37Z
zhwp>Emojiwiki
0
[[WP:AES|←]]建立内容为“<span style="font-weight:bold;font-family:'Microsoft Yahei';">{{U:Emojiwiki/username}}{{{1|}}}</span>”的新页面
wikitext
text/x-wiki
<span style="font-weight:bold;font-family:'Microsoft Yahei';">{{U:Emojiwiki/username}}{{{1|}}}</span>
1ef527690562c628292067d26408b1ee7edeaa5a
Template:Nobr
10
220
458
2020-03-31T01:52:15Z
zhwp>Xiplus
0
已保护“[[Template:Nobr]]”:高風險模板:751引用([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
#重定向 [[Template:Nowrap]]
09c557cf7fa761452db419d4f4bea3707f1d9250
Template:整齊列表
10
236
491
2020-03-31T07:27:04Z
zhwp>Xiplus
0
已保护“[[Template:整齊列表]]”:高風險模板:1784引用([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
{{#invoke:aligned table|table}}<noinclude>
{{documentation}}
</noinclude>
b46bb0255f1c93cae2a17f7589ff556cb615f050
Template:Reflist
10
172
346
2020-04-01T04:12:13Z
zhwp>Shizhao
0
取消[[Special:Contributions/Shizhao|Shizhao]]([[User talk:Shizhao|对话]])的编辑;更改回[[Special:Contributions/Chiefwei|Chiefwei]]的最后一个版本
wikitext
text/x-wiki
<div class="reflist <!--
-->{{#if: {{{1|}}}
| columns {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }}
| references-column-width
| references-column-count references-column-count-{{#if:1|{{{1}}}}} }}
| {{#if: {{{colwidth|}}}
| references-column-width }} }}" style="<!--
-->{{#if: {{{1|}}}
| {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }}
| {{column-width|{{#if:1|{{{1}}}}}}}
| {{column-count|{{#if:1|{{{1}}}}}}} }}
| {{#if: {{{colwidth|}}}
| {{column-width|{{{colwidth}}}}} }} }} list-style-type: <!--
-->{{{liststyle|{{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = decimal}}}}};">
{{{list|{{#tag:references|{{{refs|}}}|group={{{group|}}}}}}}}</div><noinclude>
{{Documentation}}
</noinclude>
4795d8947cf53545753ca196611b842301a04324
Module:Fullurl
828
42
79
2020-06-23T00:21:12Z
zhwp>Xiplus-abot
0
已保护“[[Module:Fullurl]]”:高風險模板:2748引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
local p = {}
local yesno = require('Module:Yesno')
local mError = require('Module:Error').error
function p._fullurl(args)
local paid = ''
local title = args['title'] or args[1] or args['1'] or tostring(mw.title.getCurrentTitle())
if title == '' then
--不能讓title變空值,否則url會返回nil
title = tostring(mw.title.getCurrentTitle())
end
local text = args['text'] or args[2] or args['1'] or title
for k, v in pairs( args ) do
if ((k == 'title') or (k == 1) or (k == '1') or (k == 'text') or (k == 2) or (k == '2') or (k == 'onlyurl') or (k == 'paid')) then
if (k == 'paid') then
if paid == '' then
paid = mw.text.trim(v)
else
paid = paid .. '&' .. mw.text.trim(v)
end
end
else
if paid == '' then
paid = k .. '=' .. mw.text.trim(v)
else
paid = paid .. '&' .. k .. '=' .. mw.text.trim(v)
end
end
end
local url = tostring(mw.uri.fullUrl(title,paid))
local plainlink = '<span class="plainlinks">[' .. url .. ' ' .. text .. ']</span>'
if (args['action'] == 'submit') then
return plainlink .. mError{'[[Module:Fullur]]錯誤:<code>|action=submin</code>不是有效的值,請使用<code>|action=edit</code>。'}
else
if yesno(args['onlyurl']) then
return url
else
return plainlink
end
end
end
function p.fullurl(frame)
local args = {}
for k, v in pairs( frame.args ) do
args[k] = v
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
return p._fullurl(args)
end
function p._fullurl2(title ,paid, text)
return '<span class="plainlinks">[' .. tostring(mw.uri.fullUrl(title,paid)) .. ' ' .. text .. ']</span>'
end
--[=[
function p.hosturl ()
return "//zh.wikipedia.org"
end
function p.scripturl ()
return p.hosturl () .. "/w"
end
function p.index ()
return p.scripturl () .. "/index.php"
end
function p.articlepath ()
return p () .. "/wiki"
end
p["index.php"] = function ()
return p.index ()
end
p["api.php"] = function ()
return p.scripturl () .. "/api.php"
end
p["rest.php"] = function (frame)
return p.scripturl () .. "/rest.php"
end
]=]--
return p
a16d8a94b2b7a8090d4736d5e0b986cce97ff318
Module:Shortcut
828
47
87
2020-06-23T00:32:23Z
zhwp>Xiplus-abot
0
已保护“[[Module:Shortcut]]”:高風險模板:2222引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
-- This module implements {{shortcut}}.
-- Set constants
local CONFIG_MODULE = 'Module:Shortcut/config'
-- Load required modules
local checkType = require('libraryUtil').checkType
local yesno = require('Module:Yesno')
local p = {}
function p._getshortname(frame)
return frame:expandTemplate{title = "Lan",args = {["zh-hans"]="快捷方式",["zh-hant"]="捷徑"}}
end
function p.getshortlink(frame)
return "[[Wikipedia:捷徑|" .. p._getshortname(frame) .. "]]"
end
function p.getshortlink_policy(frame)
return "[[Wikipedia:捷徑|方針" .. p._getshortname(frame) .. "]]"
end
local function message(msg, ...)
return mw.message.newRawMessage(msg, ...):plain()
end
local function makeCategoryLink(cat)
return string.format('[[%s:%s]]', mw.site.namespaces[14].name, cat)
end
function p._main(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = {shortcut}
}
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
if yesno(options.policy) then
shortcutHeading = p.getshortlink_policy(frame)
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain plainlist noprint')
:attr('role', 'note')
if options.float == 'left' then
shortcutList:addClass('module-shortcutboxplain-left')
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._main(shortcuts, options, frame)
end
function p._ombx(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = {shortcut}
}
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-omboxshortcutplain plainlist noprint')
:attr('role', 'note')
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.ombox(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._ombx(shortcuts, options, frame)
end
function p._template(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = '{{'
.. frame:expandTemplate{
title = 'Template_shortcut/link',
args = {shortcut}
}..'}}'
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', 'Template:'..anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(cfg['shortcut-heading'], nShortcuts)
shortcutHeading = shortcutHeading
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain plainlist noprint')
:attr('role', 'note')
if options.float == 'left' then
shortcutList:addClass('module-shortcutboxplain-left')
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.template(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._template(shortcuts, options, frame)
end
function p._ombx_template(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = '{{'
.. frame:expandTemplate{
title = 'Template_shortcut/link',
args = {shortcut}
}..'}}'
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', 'Template:'..anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-omboxshortcutplain plainlist noprint')
:attr('role', 'note')
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.ombox_template(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._ombx_template(shortcuts, options, frame)
end
return p
35e3570422190b34fe2fc94ccd9380657b0b5165
Module:Shortcut/config
828
48
89
2020-06-23T00:32:33Z
zhwp>Xiplus-abot
0
已保护“[[Module:Shortcut/config]]”:高風險模板:2205引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
-- This module holds configuration data for [[Module:Shortcut]].
return {
-- The heading at the top of the shortcut box. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['shortcut-heading'] = '[[Wikipedia:捷徑|-{zh-hans:快捷方式;zh-hant:捷徑}-]]',
-- The error message to display when a shortcut is invalid (is not a string, or
-- is the blank string). It accepts the following parameter:
-- $1 - the number of the shortcut in the argument list. (required)
['invalid-shortcut-error'] = '捷徑「#$1」無效(捷徑必須為' ..
'字串且長度至少為1個字元)[[Category:需要修正維基百科捷徑框參數的頁面|{{PAGENAME}}]]',
-- The error message to display when no shortcuts or other displayable content
-- were specified. (required)
['no-content-error'] = '錯誤:沒有指定捷徑名稱並且參數<code>msg</code>沒有定義。[[Category:需要修正維基百科捷徑框參數的頁面|{{PAGENAME}}]]',
-- A category to add when the no-content-error message is displayed. (optional)
--[[
我們並沒有個分類
['no-content-error-category'] = 'Shortcut模板中缺乏參數',
]]--
}
4ceb810cfde3ea15230441bf7f30de4ed0177b2c
Template:Uses Lua
10
105
204
2020-07-30T04:30:44Z
zhwp>SunAfterRain
0
看來沒什麼用啊
wikitext
text/x-wiki
<includeonly>{{#iferror:{{#invoke:Lua banner|main}}|{{#invoke:Lua banner|main2}}}}</includeonly><noinclude>
{{ {{FULLPAGENAME}} |Module:Lua banner}}
{{模板文件}}
</noinclude>
ec2cfd9808cb58e75e6f7687c9b85dd98ee2db4e
Template:Rellink
10
190
396
2020-08-14T13:27:12Z
zhwp>Xiplus-abot
0
已更改“[[Template:Rellink]]”的保护等级:高風險模板:1374引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
#重定向 [[Template:Hatnote]]
cdce4d78e74458e05e7054ffb0c0faa2d571b546
那艺娜维基:NoEdit
4
23
41
2020-08-14T13:28:42Z
zhwp>Xiplus-abot
0
已更改“[[Template:NoEdit]]”的保护等级:高風險模板:1600引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{#if:{{{|}}}<!--
产生没有编辑按钮的标题 -->|<div class="noedit">
={{{|}}}
</div><!--
编辑首段按钮不出现 -->|<span id="no-edit-0"></span><!--
结束 -->}}</includeonly><noinclude>
{{模板文档}}
</noinclude>
2908b829aa6bf620e236da30d2e5c6bc6c5b57d4
Template:NoEdit
10
51
95
2020-08-14T13:28:42Z
zhwp>Xiplus-abot
0
已更改“[[Template:NoEdit]]”的保护等级:高風險模板:1600引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{#if:{{{|}}}<!--
产生没有编辑按钮的标题 -->|<div class="noedit">
={{{|}}}
</div><!--
编辑首段按钮不出现 -->|<span id="no-edit-0"></span><!--
结束 -->}}</includeonly><noinclude>
{{模板文档}}
</noinclude>
2908b829aa6bf620e236da30d2e5c6bc6c5b57d4
Template:Link-ru
10
311
647
2020-08-17T00:33:51Z
zhwp>Xiplus-abot
0
已更改“[[Template:Link-ru]]”的保护等级:高風險模板:5111引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
#Redirect [[Template:Internal link helper/ru]]
675abb3e5e500b242e1ae89d4cfd2ac1fe639d7d
Module:Color contrast
828
268
558
2020-08-17T04:06:20Z
zhwp>Xiplus-abot
0
已更改“[[Module:Color contrast]]”的保护等级:高風險模板:34549引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB (v)
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum(R, G, B)
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum(h, s, l)
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum(c)
if (c == nil) then
return ''
end
-- html '#' entity
c = c:gsub("#", "#")
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- unstrip nowiki strip markers
c = mw.text.unstripNoWiki(c)
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
-- This exports the function for use in other modules.
-- The colour is passed as a string.
function p._lum(color)
return color2lum(color)
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local css = (args['css'] and args['css'] ~= '') and true or false
local v1 = color2lum(args[1] or '')
local c2 = args[2] or '#FFFFFF'
local v2 = color2lum(c2)
local c3 = args[3] or '#000000'
local v3 = color2lum(c3)
local ratio1 = -1;
local ratio2 = -1;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
if css then
local c1 = args[1] or ''
if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c1 = '#' .. c1
end
if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c2 = '#' .. c2
end
if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c3 = '#' .. c3
end
return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'
end
return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''
end
function p._ratio(args)
local v1 = color2lum(args[1])
local v2 = color2lum(args[2])
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', 'black'
local lum_bg, lum_fg = 1, 0
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '#', '#'), ';')
for k = 1,#slist do
local s = slist[k]
local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
--[[
Use {{#invoke:Color contrast|somecolor}} directly or
{{#invoke:Color contrast}} from a wrapper template.
Parameters:
-- |1= — required; A color to check.
--]]
function p.lum(frame)
local color = frame.args[1] or frame:getParent().args[1]
return p._lum(color)
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
1e399769117591366a63f62996c9a407077cc711
Module:Color contrast/colors
828
269
560
2020-08-17T04:06:30Z
zhwp>Xiplus-abot
0
已更改“[[Module:Color contrast/colors]]”的保护等级:高風險模板:34645引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
6ae47fdb24de4eed5ec26d203faf5341a388987b
Module:Icon
828
88
170
2020-08-17T04:08:20Z
zhwp>Xiplus-abot
0
已更改“[[Module:Icon]]”的保护等级:高風險模板:29469引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
Scribunto
text/plain
-- This module implements [[Template:Icon]].
local data = mw.loadData('Module:Icon/data')
local p = {}
function p._main(args)
local code = args.class or args[1]
local iconData
if code then
code = code:match('^%s*(.-)%s*$'):lower() -- trim whitespace and put in lower case
iconData = data[code]
end
if not iconData then
iconData = data._DEFAULT
end
return string.format(
'[[File:%s%s|%s|link=]]',
iconData.image,
iconData.tooltip and '|' .. iconData.tooltip or '',
args.size or '16x16px'
)
end
function p.main(frame)
local args = {}
for k, v in pairs(frame:getParent().args) do
args[k] = v
end
return p._main(args)
end
return p
2a9d51e44f8cd64c8eeb17655d5238da36908650
Template:About
10
57
108
2020-08-17T05:02:39Z
zhwp>Xiplus-abot
0
已更改“[[Template:About]]”的保护等级:高風險模板:7904引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{#invoke:about|about}}</includeonly><noinclude>{{Documentation}}</noinclude>
f33ff16000b289ea53090134dcae2e291c87c043
Template:Birth date
10
232
483
2020-08-17T05:04:59Z
zhwp>Xiplus-abot
0
已更改“[[Template:Birth date]]”的保护等级:高風險模板:16867引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<span style="display:none">(<span class="bday">{{{1|{{{year}}}}}}-{{padleft:{{MONTHNUMBER|{{{2|{{{month}}}}}}}}|2|0}}-{{padleft:{{{3|{{{day}}}}}}|2|0}}</span>)</span>{{#expr:{{{1|{{{year<noinclude>|1900</noinclude>}}}}}}}}年{{#if:{{{df|}}}
|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日
|{{MONTHNAME|{{{2|{{{month<noinclude>|1</noinclude>}}}}}}}}{{#expr:{{{3|{{{day<noinclude>|1</noinclude>}}}}}}}}日
}}<noinclude>
{{Documentation|Template:Birth date and age/doc}}
</noinclude>
f5d04281beeaddf72fa418cea3cd3faac5db8b4e
Template:Userbox
10
259
540
2020-08-17T05:16:00Z
zhwp>Xiplus-abot
0
已更改“[[Template:Userbox]]”的保护等级:高風險模板:24995引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{#invoke:userbox|userbox}}<noinclude>{{doc}}</noinclude>
d5a8edeeebb1c69bbe874bb8206bd663042b933b
Template:Infobox person/height
10
216
450
2020-08-17T10:50:52Z
zhwp>Xiplus-abot
0
已更改“[[Template:Infobox person/height]]”的保护等级:高風險模板:14625引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{infobox person/height/locate|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{{1|}}}<!--
-->|metre|m}}<!--
-->|meter|m}}<!--
-->|centi|c}}<!--
-->|feet|ft}}<!--
-->|foot|ft}}<!--
-->|inches|in}}<!--
-->|inch|in}}<!--
-->|ms|m}}<!--
-->|ins|in}}<!--
-->}}<noinclude>
{{Documentation}}
</noinclude>
8ed2c6523a6b3dbe26e7c4aa5710cb3203601bf2
Template:Birth date and age
10
225
469
2020-08-17T11:06:46Z
zhwp>Xiplus-abot
0
已更改“[[Template:Birth date and age]]”的保护等级:高風險模板:61259引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly><span style="display:none"> (<span class="bday">{{{1|{{{year}}}}}}-{{padleft:{{{2|{{{month}}}}}}|2|0}}-{{padleft:{{{3|{{{day}}}}}}|2|0}}</span>) </span>{{{1|{{{year}}}}}}年{{#if:{{{df|}}}|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日}}<span class="noprint ForceAgeToShow">({{age | {{{1|{{{year}}}}}} | {{{2|{{{month}}}}}} | {{{3|{{{day}}}}}} }}歲)</span></includeonly><noinclude>
{{documentation|Template:Birth date and age/doc}}
</noinclude>
42ca66b5d055e872542b96690c44bd8f7e691dec
Template:Column-width
10
182
370
2020-08-17T11:13:27Z
zhwp>Xiplus-abot
0
已更改“[[Template:Column-width]]”的保护等级:高風險模板:33647引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly>-moz-column-width: {{{1|30em}}}; -webkit-column-width: {{{1|30em}}}; column-width: {{{1|30em}}};</includeonly><noinclude>
{{documentation}}
</noinclude>
f6fbe6dee4c0e796111386c4d1fe94fcbcd77c7a
那艺娜维基:Div col end
4
16
27
2020-08-17T11:17:27Z
zhwp>Xiplus-abot
0
已更改“[[Template:Div col end]]”的保护等级:高風險模板:7578引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly></div></includeonly><noinclude>
{{Documentation|Template:Div col/doc}}
</noinclude>
78088d41c21d779e3722f220fcc9773dfbbc1e4f
Template:Div col end
10
40
75
2020-08-17T11:17:27Z
zhwp>Xiplus-abot
0
已更改“[[Template:Div col end]]”的保护等级:高風險模板:7578引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<includeonly></div></includeonly><noinclude>
{{Documentation|Template:Div col/doc}}
</noinclude>
78088d41c21d779e3722f220fcc9773dfbbc1e4f
Template:Efn
10
187
384
2020-08-17T11:20:47Z
zhwp>Xiplus-abot
0
已更改“[[Template:Efn]]”的保护等级:高風險模板:6090引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<noinclude><!--
****** 注意 *****
請勿添加任何中文的「註」或「注」功能,
否則會干擾後台對下面幾個保留字的操作,
所有中文功能已遷移至[[Template:noteTag]]。
--></noinclude><includeonly>{{#if:{{{name|}}}
|{{#tag:ref|{{{1|{{{reference|}}}}}}|name={{{name|}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group|}}}
| #default = lower-alpha
}}
}}
|{{#tag:ref|{{{1|{{{reference|}}}}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group|}}}
| #default = lower-alpha
}}
}}
}}</includeonly><noinclude>
{{documentation|Template:notelist/doc}}
</noinclude>
b05db3eed085ea7cf437f05625e1e71eedea9e85
Template:En icon
10
186
378
2020-08-17T11:21:27Z
zhwp>Xiplus-abot
0
已更改“[[Template:En icon]]”的保护等级:高風險模板:61287引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{language icon|en|英文}}<noinclude>{{Documentation}}</noinclude>
70faf378dd9cf75c11eb74120055d9f7e8ffc10c
那艺娜维基:Fullurl
4
11
17
2020-08-17T11:26:17Z
zhwp>Xiplus-abot
0
已更改“[[Template:Fullurl]]”的保护等级:高風險模板:7145引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<span class="plainlinks">[{{fullurl:{{{1}}}|{{{2}}}}} {{{3}}}]</span><noinclude>
{{documentation}}</noinclude>
9c51dda6ddd9f9055ed3843b256871781d737593
Template:Fullurl
10
34
63
2020-08-17T11:26:17Z
zhwp>Xiplus-abot
0
已更改“[[Template:Fullurl]]”的保护等级:高風險模板:7145引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<span class="plainlinks">[{{fullurl:{{{1}}}|{{{2}}}}} {{{3}}}]</span><noinclude>
{{documentation}}</noinclude>
9c51dda6ddd9f9055ed3843b256871781d737593
Template:Icon
10
87
168
2020-08-17T11:29:17Z
zhwp>Xiplus-abot
0
已更改“[[Template:Icon]]”的保护等级:高風險模板:29470引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{#invoke:Icon|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
bd5b855953c5eec9d9c48400aa39315cb4218558
Template:Ifempty
10
252
521
2020-08-17T11:29:57Z
zhwp>Xiplus-abot
0
已更改“[[Template:Ifempty]]”的保护等级:高風險模板:23645引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
#重定向 [[Template:If empty]]
462862e6cf0a8b300838914bb395b8c0207abdcc
那艺娜维基:No redirect
4
10
15
2020-08-17T11:46:08Z
zhwp>Xiplus-abot
0
已更改“[[Template:No redirect]]”的保护等级:高風險模板:9505引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}|{{{2}}}]]|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}]]}}
}}<noinclude>{{lua|Module:Redirect}}
{{documentation}}
</noinclude>
996c1e73b0906e1e05cab3f9aaff13ea04646ff8
Template:No redirect
10
33
61
2020-08-17T11:46:08Z
zhwp>Xiplus-abot
0
已更改“[[Template:No redirect]]”的保护等级:高風險模板:9505引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}|{{{2}}}]]|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}]]}}
}}<noinclude>{{lua|Module:Redirect}}
{{documentation}}
</noinclude>
996c1e73b0906e1e05cab3f9aaff13ea04646ff8
Template:Notelist
10
185
376
2020-08-17T11:48:08Z
zhwp>Xiplus-abot
0
已更改“[[Template:Notelist]]”的保护等级:高風險模板:6533引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
<noinclude><!--
****** 注意 ******
請勿添加任何中文的「註」或「注」功能,
否則會干擾後台對下面幾個保留字的操作,
所有中文功能已遷移至[[Template:noteFoot]]。
--></noinclude><includeonly><div class="notelist" style="list-style-type: {{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = lower-alpha
}};">
{{#tag:references|{{{1|{{{refs|{{{notes|}}}}}}}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = lower-alpha
}}}}
</div></includeonly><noinclude>
{{documentation}}
</noinclude>
c3d897b9da64d14bb0ec824c875158105b892281
Template:Ombox
10
96
186
2020-08-17T11:49:48Z
zhwp>Xiplus-abot
0
已更改“[[Template:Ombox]]”的保护等级:高風險模板:39438引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
0e54065432d540737b9e56c4e3a8e7f74d4534ea
Template:Remove first word
10
219
456
2020-08-17T11:56:09Z
zhwp>Xiplus-abot
0
已更改“[[Template:Remove first word]]”的保护等级:高風險模板:25474引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:String|replace|source={{{1}}}|pattern=^[^{{{sep|%s}}}]*{{{sep|%s}}}*|replace=|plain=false}}<noinclude>{{Documentation}}</noinclude>
df7a9e692f68be1581be06af5f51eaed5483b4c8
Template:Resize
10
229
477
2020-08-17T11:56:39Z
zhwp>Xiplus-abot
0
已更改“[[Template:Resize]]”的保护等级:高風險模板:16244引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
{{#if:{{{2|}}}
|<span style="font-size:{{{1|}}};">{{{2|}}}</span>
|<span style="font-size:90%;">{{{1}}}</span>
}}<noinclude>
{{doc}}
<!--PLEASE ADD CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS-->
</noinclude>
c7461944f74c760bc5b2d94c8b7c42c6c024459c
Template:!!
10
188
386
2020-08-17T12:27:17Z
zhwp>Xiplus-abot
0
已更改“[[Template:!!]]”的保护等级:高風險模板:85263引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
||<noinclude>{{Documentation}}</noinclude>
868ada04d0812624aa39b895a7fc297c0827d92d
Template:Bulleted list
10
238
495
2020-08-17T16:16:47Z
zhwp>Pseudo Classes
0
1 版本来自 [[:en:Template:Bulleted_list]]
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|bulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
37ac60a83d34c2df10fb601002557ad1b55919bb
Userboxbottom
0
285
593
2020-08-18T04:49:47Z
zhwp>Xiplus-abot
0
已更改“[[Template:Userboxbottom]]”的保护等级:高風險模板:3748引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
<includeonly>
|}</includeonly><noinclude>{{Documentation}}
</noinclude>
b333f86f0f9f9c041965fdf594b197311bb4b36c
Template:Userboxbottom
10
297
617
2020-08-18T04:49:47Z
zhwp>Xiplus-abot
0
已更改“[[Template:Userboxbottom]]”的保护等级:高風險模板:3748引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
<includeonly>
|}</includeonly><noinclude>{{Documentation}}
</noinclude>
b333f86f0f9f9c041965fdf594b197311bb4b36c
Userboxbottom/doc
0
290
603
2020-12-13T18:32:52Z
zhwp>SCP-2000
0
revert (vandalism)
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
收尾{{tl|Userboxtop}}之參數模板。
== 使用方法 ==
參閱{{tl|Userboxtop}}與{{tl|Userboxbreak}}的語法範例。
== 注意事项 ==
本模板並非空白。
== 參見 ==
*[[Template:Userboxtop]]
*[[Template:Userboxbreak]]
==重定向==
* {{tl|Boxboxbottom}} 重定向至此。
* {{tl|Userboxbot}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
0592e0bd8558911d64b9785eefecf681129bac45
Template:Userboxbottom/doc
10
299
621
2020-12-13T18:32:52Z
zhwp>SCP-2000
0
revert (vandalism)
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
收尾{{tl|Userboxtop}}之參數模板。
== 使用方法 ==
參閱{{tl|Userboxtop}}與{{tl|Userboxbreak}}的語法範例。
== 注意事项 ==
本模板並非空白。
== 參見 ==
*[[Template:Userboxtop]]
*[[Template:Userboxbreak]]
==重定向==
* {{tl|Boxboxbottom}} 重定向至此。
* {{tl|Userboxbot}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
0592e0bd8558911d64b9785eefecf681129bac45
Userboxtop/doc
0
296
615
2020-12-15T17:26:12Z
zhwp>Renamed user t5AlUMu36q
0
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
這個模板可以將好幾個用戶框和其連帶的圖片整理收集為一個整齊的區塊。
過去有[[Wikipedia:什么是条目|條目]]使用此模板,但現今條目'''不應'''再使用此模板。若條目確有內容需要框住,請使用{{tlx|Stack}}模板。
== 使用方法 ==
<pre><nowiki>{{userboxtop
| align =
| backgroundcolor =
| bordercolor =
| extra-css =
| textcolor =
| toptext =
| width =
}}
[userboxes]
{{userboxbottom}}</nowiki></pre>
所有參數都是'''選擇性的'''。
{{UF-hcard-part}}
===個人化===
以下有一些詳細介紹
{| class="wikitable"
|-
! 參數
! 數值範圍
|-
| <code>align</code>
| <code>left</code>, <code>center</code>, 或<code>right</code>(預設值)
|-
| <code>backgroundcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#FFFFFF</tt>。
|-
| <code>bordercolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#99B3FF</tt>。
|-
| <code>extra-css</code>
| 可使用額外[[Cascading Style Sheets|CSS]]資訊。
|-
| <code>textcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#000000</tt>。
|-
| <code>toptext</code>
| 取代預設的{{tl|Userboxes}}文字和链接。可包含wiki-markup。
|-
| <code>width</code>
| 調整用戶框的闊度(預設為248px)。
|}
中間可插入新行以及重組分類。詳情可參看{{tl|Userboxbreak}}。
==隱藏用戶框==
你可以隱藏用了這個模板的用戶框。只需在你的個人CSS頁(如果你的外觀設定爲Monobook,就是[[Special:Mypage/monobook.css|monobook.css]],其他外觀同理) 中加入<code><nowiki>.userboxes { display: none; }</nowiki></code>即可。
== 參見 ==
*[[Template:Userboxbottom]]
*[[Template:Userboxbreak]]
* [[Template:Userbox encouragement container]](将维基荣誉模板美观的收纳到用户框)
== 重定向 ==
*{{tl|Boxboxtop}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
1fc7601b7c6ffdedcd77767760003f4141bac9e5
Template:Userboxtop/doc
10
303
629
2020-12-15T17:26:12Z
zhwp>Renamed user t5AlUMu36q
0
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
這個模板可以將好幾個用戶框和其連帶的圖片整理收集為一個整齊的區塊。
過去有[[Wikipedia:什么是条目|條目]]使用此模板,但現今條目'''不應'''再使用此模板。若條目確有內容需要框住,請使用{{tlx|Stack}}模板。
== 使用方法 ==
<pre><nowiki>{{userboxtop
| align =
| backgroundcolor =
| bordercolor =
| extra-css =
| textcolor =
| toptext =
| width =
}}
[userboxes]
{{userboxbottom}}</nowiki></pre>
所有參數都是'''選擇性的'''。
{{UF-hcard-part}}
===個人化===
以下有一些詳細介紹
{| class="wikitable"
|-
! 參數
! 數值範圍
|-
| <code>align</code>
| <code>left</code>, <code>center</code>, 或<code>right</code>(預設值)
|-
| <code>backgroundcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#FFFFFF</tt>。
|-
| <code>bordercolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#99B3FF</tt>。
|-
| <code>extra-css</code>
| 可使用額外[[Cascading Style Sheets|CSS]]資訊。
|-
| <code>textcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#000000</tt>。
|-
| <code>toptext</code>
| 取代預設的{{tl|Userboxes}}文字和链接。可包含wiki-markup。
|-
| <code>width</code>
| 調整用戶框的闊度(預設為248px)。
|}
中間可插入新行以及重組分類。詳情可參看{{tl|Userboxbreak}}。
==隱藏用戶框==
你可以隱藏用了這個模板的用戶框。只需在你的個人CSS頁(如果你的外觀設定爲Monobook,就是[[Special:Mypage/monobook.css|monobook.css]],其他外觀同理) 中加入<code><nowiki>.userboxes { display: none; }</nowiki></code>即可。
== 參見 ==
*[[Template:Userboxbottom]]
*[[Template:Userboxbreak]]
* [[Template:Userbox encouragement container]](将维基荣誉模板美观的收纳到用户框)
== 重定向 ==
*{{tl|Boxboxtop}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
1fc7601b7c6ffdedcd77767760003f4141bac9e5
Template:模板鏈接
10
210
438
2020-12-18T11:09:54Z
zhwp>Q28
0
编辑工具:修复多重重定向
wikitext
text/x-wiki
#REDIRECT [[Template:Tl]]
69fe34340c46c356e0b01b31ca783b9a5e2a388d
Template:When pagename is
10
265
552
2021-01-30T07:14:45Z
zhwp>Xiplus
0
已更改“[[Template:When pagename is]]”的保护等级:[[Wikipedia:保護方針#永久保护|嵌入在MediaWiki命名空間的頁面]]([移动=仅允许管理员](无限期)[编辑=仅允许管理员](无限期))
wikitext
text/x-wiki
{{#if:x <!--Remove surrounding whitespace-->
| <!--Check for match with full pagename-->
{{{ {{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }} <!--Has data, or is empty but defined-->
| <!--Check for match with "User:Somepage/+"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|1|1}}/+
| <!--Else, are we on a subpage or a basepage?-->
{{#if:{{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|2}}
| <!--We are on a subpage, check for match with "User:Somepage/*"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|1|1}}/*
| <!--Check for match with "Somepage/*"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{PAGENAME:{{{page|}}}}} | {{PAGENAME}} }}|1|1}}/*
| <!--Check for match with "/something"-->
{{{ /{{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}
| <!--Check for match with "/somethin*"-->
{{{ /{{lc: {{padleft:|8| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}*
| <!--Check for match with "/someth*"-->
{{{ /{{lc: {{padleft:|6| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}*
| <!--Check for match with "/some*"-->
{{{ /{{lc: {{padleft:|4| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}* <!--Pad with # so "/a" doesn't match "/aaaa*"-->
| {{{subpage| {{{other|}}} }}} <!--Respecting empty parameter on purpose-->
}}}
}}}
}}}
}}}
}}}
}}}
| <!--We are on a basepage, check for match with "Somepage"-->
{{{ {{#if:{{{page|}}}| {{PAGENAME:{{{page|}}}}} | {{PAGENAME}} }}
| {{{basepage| {{{other|}}} }}} <!--Respecting empty parameter on purpose-->
}}}
}} <!--End if, are we on a subpage or a basepage?-->
}}}
}}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
cb8a18bf89fe47e27ba71ad692df00ef7313b9a4
Template:If pagename
10
264
550
2021-01-30T07:15:15Z
zhwp>Xiplus
0
已更改“[[Template:If pagename]]”的保护等级:[[Wikipedia:保護方針#永久保护|嵌入在MediaWiki命名空間的頁面]]([移动=仅允许管理员](无限期)[编辑=仅允许管理员](无限期))
wikitext
text/x-wiki
#重定向 [[Template:When pagename is]]
ce7deb49fcb3beb9fcd9da7cc735815712d4498a
那艺娜维基:Fullurl2
4
17
29
2021-01-30T07:15:45Z
zhwp>Xiplus
0
已更改“[[Template:Fullurl2]]”的保护等级:[[Wikipedia:保護方針#永久保护|嵌入在MediaWiki命名空間的頁面]]([移动=仅允许管理员](无限期)[编辑=仅允许管理员](无限期))
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:fullurl|fullurl}}<noinclude>
{{doc}}</noinclude>
bcec16f0cb14ffd7fbc29d4efa40670958541c85
Template:Fullurl2
10
41
77
2021-01-30T07:15:45Z
zhwp>Xiplus
0
已更改“[[Template:Fullurl2]]”的保护等级:[[Wikipedia:保護方針#永久保护|嵌入在MediaWiki命名空間的頁面]]([移动=仅允许管理员](无限期)[编辑=仅允许管理员](无限期))
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:fullurl|fullurl}}<noinclude>
{{doc}}</noinclude>
bcec16f0cb14ffd7fbc29d4efa40670958541c85
Template:Category handler
10
262
546
2021-01-31T10:56:09Z
zhwp>KirkLU
0
自[[Template:Category handler/sandbox]]合并[[Special:Contributions/BoyuZhang1998|BoyuZhang1998]]的[[Special:PermaLink/63994095|版本63994095]]
wikitext
text/x-wiki
{{#if:
{{#ifeq: {{lc: {{{nocat|}}} }} | true
| dontcat <!--"nocat=true", don't categorize-->
}}{{#ifeq: {{lc: {{{categories|}}} }} | no
| dontcat
}}{{#switch: {{lc: {{{category2|¬}}} }}
| yes
| ¬ = <!--Not defined-->
| #default = dontcat <!--"category2 = no/'defined but empty'/'anything'"-->
}}{{#switch: {{lc: {{{subpage|}}} }}
| no =
{{basepage subpage
|
| dontcat <!--"subpage=no" and on a subpage-->
| page = {{{page|}}} <!--For testing-->
}}
| only =
{{basepage subpage
| dontcat <!--"subpage=only" and not on a subpage-->
| page = {{{page|}}} <!--For testing-->
}}
}}
| <!--Don't categorise (result was "dontcat" or "dontcatdontcat" and so on)-->
| <!--Check blacklist-->
{{#switch:
{{#ifeq: {{lc: {{{nocat|}}} }} | false
| <!--"nocat=false", skip blacklist check-->
| {{#ifeq: {{lc: {{{categories|}}} }} | yes
| <!--Skip blacklist check-->
| {{#ifeq: {{lc: {{{category2|}}} }} | yes
| <!--Skip blacklist check-->
| {{category handler/blacklist| page = {{{page|}}} }} <!--Check blacklist-->
}}
}}
}}
| hide = <!--Blacklist returned "hide", don't categorize-->
| #default =
<!--Check if any namespace parameter is defined-->
{{#ifeq: h0#384!5nea+w9 | {{{all| {{{main| {{{talk| {{{user| {{{wikipedia| {{{file| {{{mediawiki| {{{template| {{{help| {{{category| {{{portal| {{{book| {{{wikiproject| {{{other| h0#384!5nea+w9 }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}}
| <!--No namespace parameters fed, basic usage-->
{{namespace detect
| main = {{{1|}}}
| file = {{{1|}}}
| help = {{{1|}}}
| category = {{{1|}}}
| portal = {{{1|}}}
| book = {{{1|}}}
| wikiproject = {{{1|}}}
| page = {{{page|}}} <!--For testing and demonstration-->
}}
| <!--Namespace parameters fed, advanced usage.
If "data" is a number, return the corresponding
numbered parameter, else return "data". -->
{{{all|}}}{{category handler/numbered
| 1 = {{{1|}}}
| 2 = {{{2|}}}
| 3 = {{{3|}}}
| 4 = {{{4|}}}
| 5 = {{{5|}}}
| 6 = {{{6|}}}
| 7 = {{{7|}}}
| 8 = {{{8|}}}
| 9 = {{{9|}}}
| 10 = {{{10|}}}
| data =
<!--Check what namespace, and return the data for it.
Respecting empty parameters on purpose. -->
{{namespace detect
| main = {{{main| {{{other|}}} }}}
| talk = {{{talk| {{{other|}}} }}}
| user = {{{user| {{{other|}}} }}}
| wikipedia = {{{wikipedia| {{{project| {{{other|}}} }}} }}}
| file = {{{file| {{{image| {{{other|}}} }}} }}}
| mediawiki = {{{mediawiki| {{{other|}}} }}}
| template = {{{template| {{{other|}}} }}}
| help = {{{help| {{{other|}}} }}}
| category = {{{category| {{{other|}}} }}}
| portal = {{{portal| {{{other|}}} }}}
| book = {{{book| {{{other|}}} }}}
| wikiproject = {{{wikiproject| {{{other|}}} }}}
| other = {{{other|}}} <!--Namespace special or a new namespace-->
| page = {{{page|}}} <!--For testing and demonstration-->
}}
}}
}}
}}
}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, and interwikis to Wikidata. -->
</noinclude>
c2dcb69c376e6ebdc4b416dc054b6152efc98920
Module:Lan
828
32
59
2021-02-21T14:11:23Z
zhwp>KirkLU
0
per request of [[Module_talk:Lan#編輯請求_2021-02-20]]
Scribunto
text/plain
local l={}
local getArgs
local args
l.fallbackList={
['zh']={'zh','zh-hans','zh-hant','zh-cn','zh-tw','zh-hk','zh-mo','zh-sg','zh-my'}
,['zh-hans']={'zh-hans','zh-cn','zh-sg','zh-my','zh'}
,['zh-hant']={'zh-hant','zh-tw','zh-hk','zh-mo','zh'}
,['zh-cn']={'zh-cn','zh-hans','zh-sg','zh-my','zh'}
,['zh-sg']={'zh-sg','zh-hans','zh-cn','zh-my','zh'}
,['zh-my']={'zh-my','zh-hans','zh-cn','zh-sg','zh'}
,['zh-tw']={'zh-tw','zh-hant','zh-hk','zh-mo','zh'}
,['zh-hk']={'zh-hk','zh-hant','zh-mo','zh-tw','zh'}
,['zh-mo']={'zh-mo','zh-hant','zh-hk','zh-tw','zh'}
}
function l._main(args, frame)
local userlanguage=frame:callParserFunction{ name = 'int', args = {'Conversionname'} }
--mw.message.new('Conversionname'):plain()
local fallback=l.fallbackList[userlanguage]
if fallback == nil then
fallback=l.fallbackList['zh']
end
for _,langArgName in ipairs(fallback) do
if args[langArgName] ~= nil then
return args[langArgName]
end
end
return ''
end
function l.main(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame, {parentFirst=true})
return l._main(args, frame)
end
return l
338e358c23346e2de384e3661a2924949707b3a8
Template:Navbox with collapsible groups
10
233
485
2021-02-27T03:10:11Z
zhwp>Xiplus
0
+tracking
wikitext
text/x-wiki
{{#invoke:navbox|navbox
|name = {{{name|<noinclude>Navbox with collapsible groups</noinclude>}}}
|navbar = {{{navbar|}}}
|state = {{{state|<noinclude>uncollapsed</noinclude>}}}
|border = {{{border|{{{1|}}}}}}
|title = {{{title<includeonly>|</includeonly>}}}
|above = {{{above|}}}
|image = {{{image|}}}
|imageleft = {{{imageleft|}}}
|bodyclass = {{{bodyclass|}}}
|titleclass = {{{titleclass|}}}
|aboveclass = {{{aboveclass|}}}
|belowclass = {{{belowclass|}}}
|groupclass = {{{groupclass|}}}
|listclass = {{{listclass|}}}
|imageclass = {{{imageclass|}}}
|style = {{{style|}}}{{{bodystyle|}}}
|basestyle = {{{basestyle|}}}
|titlestyle = {{{titlestyle|}}}
|abovestyle = {{{abovestyle|}}}
|belowstyle = {{{belowstyle|}}}
|imagestyle = {{{imagestyle|}}}
|imageleftstyle = {{{imageleftstyle|}}}
|list1 =
{{#if:{{{group1<includeonly>|</includeonly>}}}{{{sect1|}}}{{{section1|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr1}}} |uncollapsed |{{{state1|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group1style|}}}{{{sect1titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list1style|}}}{{{content1style|}}}
|title = {{{group1<includeonly>|</includeonly>}}}{{{sect1|}}}{{{section1|}}}<noinclude> or {{{section1}}} or {{{sect1}}}</noinclude>
|list1 = {{{list1<includeonly>|</includeonly>}}}{{{content1|}}}<noinclude> or {{{content1}}}</noinclude>
|image = {{{image1|}}}
|imageleft = {{{imageleft1|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list1|}}}{{{content1|}}}
}}
|list2 =
{{#if:{{{group2<includeonly>|</includeonly>}}}{{{sect2|}}}{{{section2|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr2}}} |uncollapsed |{{{state2|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group2style|}}}{{{sect2titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list2style|}}}{{{content2style|}}}
|title = {{{group2<includeonly>|</includeonly>}}}{{{sect2|}}}{{{section2|}}}<noinclude> or {{{section2}}} or {{{sect2}}}</noinclude>
|list1 = {{{list2<includeonly>|</includeonly>}}}{{{content2|}}}<noinclude> or {{{content2}}}</noinclude>
|image = {{{image2|}}}
|imageleft = {{{imageleft2|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list2|}}}{{{content2|}}}
}}
|list3 =
{{#if:{{{group3<includeonly>|</includeonly>}}}{{{sect3|}}}{{{section3|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr3}}} |uncollapsed |{{{state3|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group3style|}}}{{{sect3titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list3style|}}}{{{content3style|}}}
|title = {{{group3<includeonly>|</includeonly>}}}{{{sect3|}}}{{{section3|}}}<noinclude> or {{{section3}}} or {{{sect3}}}</noinclude>
|list1 = {{{list3<includeonly>|</includeonly>}}}{{{content3|}}}<noinclude> or {{{content3}}}</noinclude>
|image = {{{image3|}}}
|imageleft = {{{imageleft3|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list3|}}}{{{content3|}}}
}}
|list4 =
{{#if:{{{group4<includeonly>|</includeonly>}}}{{{sect4|}}}{{{section4|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr4}}} |uncollapsed |{{{state4|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group4style|}}}{{{sect4titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list4style|}}}{{{content4style|}}}
|title = {{{group4<includeonly>|</includeonly>}}}{{{sect4|}}}{{{section4|}}}<noinclude> or {{{section4}}} or {{{sect4}}}</noinclude>
|list1 = {{{list4<includeonly>|</includeonly>}}}{{{content4|}}}<noinclude> or {{{content4}}}</noinclude>
|image = {{{image4|}}}
|imageleft = {{{imageleft4|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list4|}}}{{{content4|}}}
}}
|list5 =
{{#if:{{{group5<includeonly>|</includeonly>}}}{{{sect5|}}}{{{section5|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr5}}} |uncollapsed |{{{state5|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group5style|}}}{{{sect5titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list5style|}}}{{{content5style|}}}
|title = {{{group5<includeonly>|</includeonly>}}}{{{sect5|}}}{{{section5|}}}<noinclude> or {{{section5}}} or {{{sect5}}}</noinclude>
|list1 = {{{list5<includeonly>|</includeonly>}}}{{{content5|}}}<noinclude> or {{{content5}}}</noinclude>
|image = {{{image5|}}}
|imageleft = {{{imageleft5|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list5|}}}{{{content5|}}}
}}
|list6 =
{{#if:{{{group6|}}}{{{sect6|}}}{{{section6|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr6}}} |uncollapsed |{{{state6|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group6style|}}}{{{sect6titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list6style|}}}{{{content6style|}}}
|title = {{{group6|}}}{{{sect6|}}}{{{section6|}}}
|list1 = {{{list6|}}}{{{content6|}}}
|image = {{{image6|}}}
|imageleft = {{{imageleft6|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list6|}}}{{{content6|<noinclude>''(...etc, to group20/sect20/section20 and list20/content20)''</noinclude>}}}
}}
|list7 =
{{#if:{{{group7|}}}{{{sect7|}}}{{{section7|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr7}}} |uncollapsed |{{{state7|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group7style|}}}{{{sect7titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list7style|}}}{{{content7style|}}}
|title = {{{group7|}}}{{{sect7|}}}{{{section7|}}}
|list1 = {{{list7|}}}{{{content7|}}}
|image = {{{image7|}}}
|imageleft = {{{imageleft7|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list7|}}}{{{content7|}}}
}}
|list8 =
{{#if:{{{group8|}}}{{{sect8|}}}{{{section8|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr8}}} |uncollapsed |{{{state8|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group8style|}}}{{{sect8titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list8style|}}}{{{content8style|}}}
|title = {{{group8|}}}{{{sect8|}}}{{{section8|}}}
|list1 = {{{list8|}}}{{{content8|}}}
|image = {{{image8|}}}
|imageleft = {{{imageleft8|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list8|}}}{{{content8|}}}
}}
|list9 =
{{#if:{{{group9|}}}{{{sect9|}}}{{{section9|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr9}}} |uncollapsed |{{{state9|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group9style|}}}{{{sect9titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list9style|}}}{{{content9style|}}}
|title = {{{group9|}}}{{{sect9|}}}{{{section9|}}}
|list1 = {{{list9|}}}{{{content9|}}}
|image = {{{image9|}}}
|imageleft = {{{imageleft9|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list9|}}}{{{content9|}}}
}}
|list10 =
{{#if:{{{group10|}}}{{{sect10|}}}{{{section10|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr10}}} |uncollapsed |{{{state10|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group10style|}}}{{{sect10titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list10style|}}}{{{content10style|}}}
|title = {{{group10|}}}{{{sect10|}}}{{{section10|}}}
|list1 = {{{list10|}}}{{{content10|}}}
|image = {{{image10|}}}
|imageleft = {{{imageleft10|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list10|}}}{{{content10|}}}
}}
|list11 =
{{#if:{{{group11|}}}{{{sect11|}}}{{{section11|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr11}}} |uncollapsed |{{{state11|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group11style|}}}{{{sect11titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list11style|}}}{{{content11style|}}}
|title = {{{group11|}}}{{{sect11|}}}{{{section11|}}}
|list1 = {{{list11|}}}{{{content11|}}}
|image = {{{image11|}}}
|imageleft = {{{imageleft11|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list11|}}}{{{content11|}}}
}}
|list12 =
{{#if:{{{group12|}}}{{{sect12|}}}{{{section12|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr12}}} |uncollapsed |{{{state12|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group12style|}}}{{{sect12titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list12style|}}}{{{content12style|}}}
|title = {{{group12|}}}{{{sect12|}}}{{{section12|}}}
|list1 = {{{list12|}}}{{{content12|}}}
|image = {{{image12|}}}
|imageleft = {{{imageleft12|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list12|}}}{{{content12|}}}
}}
|list13 =
{{#if:{{{group13|}}}{{{sect13|}}}{{{section13|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr13}}} |uncollapsed |{{{state13|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group13style|}}}{{{sect13titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list13style|}}}{{{content13style|}}}
|title = {{{group13|}}}{{{sect13|}}}{{{section13|}}}
|list1 = {{{list13|}}}{{{content13|}}}
|image = {{{image13|}}}
|imageleft = {{{imageleft13|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list13|}}}{{{content13|}}}
}}
|list14 =
{{#if:{{{group14|}}}{{{sect14|}}}{{{section14|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr14}}} |uncollapsed |{{{state14|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group14style|}}}{{{sect14titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list14style|}}}{{{content14style|}}}
|title = {{{group14|}}}{{{sect14|}}}{{{section14|}}}
|list1 = {{{list14|}}}{{{content14|}}}
|image = {{{image14|}}}
|imageleft = {{{imageleft14|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list14|}}}{{{content14|}}}
}}
|list15 =
{{#if:{{{group15|}}}{{{sect15|}}}{{{section15|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr15}}} |uncollapsed |{{{state15|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group15style|}}}{{{sect15titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list15style|}}}{{{content15style|}}}
|title = {{{group15|}}}{{{sect15|}}}{{{section15|}}}
|list1 = {{{list15|}}}{{{content15|}}}
|image = {{{image15|}}}
|imageleft = {{{imageleft15|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list15|}}}{{{content15|}}}
}}
|list16 =
{{#if:{{{group16|}}}{{{sect16|}}}{{{section16|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr16}}} |uncollapsed |{{{state16|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group16style|}}}{{{sect16titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list16style|}}}{{{content16style|}}}
|title = {{{group16|}}}{{{sect16|}}}{{{section16|}}}
|list1 = {{{list16|}}}{{{content16|}}}
|image = {{{image16|}}}
|imageleft = {{{imageleft16|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list16|}}}{{{content16|}}}
}}
|list17 =
{{#if:{{{group17|}}}{{{sect17|}}}{{{section17|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr17}}} |uncollapsed |{{{state17|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group17style|}}}{{{sect17titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list17style|}}}{{{content17style|}}}
|title = {{{group17|}}}{{{sect17|}}}{{{section17|}}}
|list1 = {{{list17|}}}{{{content17|}}}
|image = {{{image17|}}}
|imageleft = {{{imageleft17|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list17|}}}{{{content17|}}}
}}
|list18 =
{{#if:{{{group18|}}}{{{sect18|}}}{{{section18|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr18}}} |uncollapsed |{{{state18|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group18style|}}}{{{sect18titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list18style|}}}{{{content18style|}}}
|title = {{{group18|}}}{{{sect18|}}}{{{section18|}}}
|list1 = {{{list18|}}}{{{content18|}}}
|image = {{{image18|}}}
|imageleft = {{{imageleft18|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list18|}}}{{{content18|}}}
}}
|list19 =
{{#if:{{{group19|}}}{{{sect19|}}}{{{section19|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr19}}} |uncollapsed |{{{state19|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group19style|}}}{{{sect19titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list19style|}}}{{{content19style|}}}
|title = {{{group19|}}}{{{sect19|}}}{{{section19|}}}
|list1 = {{{list19|}}}{{{content19|}}}
|image = {{{image19|}}}
|imageleft = {{{imageleft19|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list19|}}}{{{content19|}}}
}}
|list20 =
{{#if:{{{group20|}}}{{{sect20|}}}{{{section20|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr20}}} |uncollapsed |{{{state20|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group20style|}}}{{{sect20titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list20style|}}}{{{content20style|}}}
|title = {{{group20|}}}{{{sect20|}}}{{{section20|}}}
|list1 = {{{list20|}}}{{{content20|}}}
|image = {{{image20|}}}
|imageleft = {{{imageleft20|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list20|}}}{{{content20|}}}
}}
|below = {{{below|}}}
| tracking = {{{tracking|}}}
}}<noinclude>
{{documentation}}
</noinclude>
808c72ef412d47bc3360afb751d679608858d38b
Template:Navbox
10
73
140
2021-02-28T01:59:16Z
zhwp>Xiplus
0
includeonly
wikitext
text/x-wiki
<includeonly>{{#invoke: Navbox | navbox }}</includeonly><noinclude>{{documentation}}<!-- Add categories and interwikis to the /doc sub-page --></noinclude>
2b5d285f265745c44fc40f51d6e9bfa0a05efc9a
Template:Hatnote
10
181
368
2021-03-08T00:08:22Z
zhwp>Xiplus-abot
0
已更改“[[Template:Hatnote]]”的保护等级:高風險模板:107380引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<includeonly>{{#invoke:Hatnote|hatnote}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
4a1d1028d07c9056022807a96051e1c82cf2a1c7
Template:Para
10
79
152
2021-03-08T00:09:02Z
zhwp>Xiplus-abot
0
已更改“[[Template:Para]]”的保护等级:高風險模板:130407引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<code lang="en" class="nowrap">|{{#if:{{{1|}}}|{{{1}}}=}}{{{2|}}}</code><noinclude>
{{Documentation}}
[[Category:輸入支援模板]]
[[Category:格式模板]]
<!--Categories and interwikis go near the bottom of the /doc subpage.-->
</noinclude>
5299c3a8d06166c23855a3461733c7cc4698830d
Template:High-use
10
113
220
2021-03-23T06:17:07Z
zhwp>Xiplus
0
[[Special:PermaLink/64874541#High-use模板相关|改為模組]]
wikitext
text/x-wiki
{{#invoke:High-use|main|1={{{1|}}}|2={{{2|}}}|all-pages={{{all-pages|}}}|info={{{info|}}}|demo={{{demo|}}}|form={{{form|}}}|expiry={{{expiry|}}}}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwiki links go to Wikidata, thank you! -->
</noinclude>
a0b2a1139d339dbb30f81db49ec4775f8d55871f
Module:Protection banner
828
109
212
2021-05-22T15:24:50Z
zhwp>Xiplus
0
回退到由[[Special:Contributions/Pseudo Classes|Pseudo Classes]]([[User talk:Pseudo Classes|討論]])做出的修訂版本61213875:BREAKING CHANGE
Scribunto
text/plain
-- This module implements {{pp-meta}} and its daughter templates such as
-- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.
-- Initialise necessary modules.
require('Module:No globals')
local makeFileLink = require('Module:File link')._main
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main
local yesno = require('Module:Yesno')
-- Lazily initialise modules and objects we don't always need.
local getArgs, makeMessageBox, lang
-- Set constants.
local CONFIG_MODULE = 'Module:Protection banner/config'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function makeCategoryLink(cat, sort)
if cat then
return string.format(
'[[%s:%s|%s]]',
mw.site.namespaces[14].name,
cat,
sort
)
end
end
-- Validation function for the expiry and the protection date
local function validateDate(dateString, dateType)
if not lang then
lang = mw.language.getContentLanguage()
end
local success, result = pcall(lang.formatDate, lang, 'U', dateString)
if success then
result = tonumber(result)
if result then
return result
end
end
error(string.format(
'%s「%s」並非有效的格式!',
dateType,
tostring(dateString)
), 4)
end
local function makeFullUrl(page, query, display)
return require('Module:Fullurl')._fullurl2(page, query, display)
end
-- Given a directed graph formatted as node -> table of direct successors,
-- get a table of all nodes reachable from a given node (though always
-- including the given node).
local function getReachableNodes(graph, start)
local toWalk, retval = {[start] = true}, {}
while true do
-- Can't use pairs() since we're adding and removing things as we're iterating
local k = next(toWalk) -- This always gets the "first" key
if k == nil then
return retval
end
toWalk[k] = nil
retval[k] = true
for _,v in ipairs(graph[k]) do
if not retval[v] then
toWalk[v] = true
end
end
end
end
--------------------------------------------------------------------------------
-- Protection class
--------------------------------------------------------------------------------
local Protection = {}
Protection.__index = Protection
Protection.supportedActions = {
edit = true,
move = true,
autoreview = true,
upload = true
}
Protection.bannerConfigFields = {
'text',
'explanation',
'tooltip',
'alt',
'link',
'image'
}
function Protection.new(args, cfg, title)
local obj = {}
obj._cfg = cfg
obj.title = title or mw.title.getCurrentTitle()
-- Set action
if not args.action then
obj.action = 'edit'
elseif Protection.supportedActions[args.action] then
obj.action = args.action
else
error(string.format(
'未知動作「%s」',
tostring(args.action)
), 3)
end
-- Set level
obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)
if not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then
-- Users need to be autoconfirmed to move pages anyway, so treat
-- semi-move-protected pages as unprotected.
obj.level = '*'
end
-- Set expiry
local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title)
if effectiveExpiry == 'infinity' then
obj.expiry = 'indef'
elseif effectiveExpiry ~= 'unknown' then
obj.expiry = validateDate(effectiveExpiry, '截止時間')
end
-- Set reason
if args[1] then
obj.reason = mw.ustring.lower(args[1])
if obj.reason:find('|') then
error('理由中不得存在「|」!', 3)
end
end
-- Set protection date
if args.date then
obj.protectionDate = validateDate(args.date, '保護日期')
end
-- Set banner config
do
obj.bannerConfig = {}
local configTables = {}
if cfg.banners[obj.action] then
configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason]
end
if cfg.defaultBanners[obj.action] then
configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level]
configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default
end
configTables[#configTables + 1] = cfg.masterBanner
for i, field in ipairs(Protection.bannerConfigFields) do
for j, t in ipairs(configTables) do
if t[field] then
obj.bannerConfig[field] = t[field]
break
end
end
end
end
return setmetatable(obj, Protection)
end
function Protection:isProtected()
return self.level ~= '*'
end
function Protection:isTemporary()
return type(self.expiry) == 'number'
end
function Protection:makeProtectionCategory()
local cfg = self._cfg
local title = self.title
-- Exit if the page is not protected.
if not self:isProtected() then
return ''
end
-- Get the expiry key fragment.
local expiryFragment
if self.expiry == 'indef' then
expiryFragment = self.expiry
elseif type(self.expiry) == 'number' then
expiryFragment = 'temp'
end
-- Get the namespace key fragment.
local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]
if not namespaceFragment and title.namespace % 2 == 1 then
namespaceFragment = 'talk'
end
-- Define the order that key fragments are tested in. This is done with an
-- array of tables containing the value to be tested, along with its
-- position in the cfg.protectionCategories table.
local order = {
{val = expiryFragment, keypos = 1},
{val = namespaceFragment, keypos = 2},
{val = self.reason, keypos = 3},
{val = self.level, keypos = 4},
{val = self.action, keypos = 5}
}
--[[
-- The old protection templates used an ad-hoc protection category system,
-- with some templates prioritising namespaces in their categories, and
-- others prioritising the protection reason. To emulate this in this module
-- we use the config table cfg.reasonsWithNamespacePriority to set the
-- reasons for which namespaces have priority over protection reason.
-- If we are dealing with one of those reasons, move the namespace table to
-- the end of the order table, i.e. give it highest priority. If not, the
-- reason should have highest priority, so move that to the end of the table
-- instead.
--]]
table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3))
--[[
-- Define the attempt order. Inactive subtables (subtables with nil "value"
-- fields) are moved to the end, where they will later be given the key
-- "all". This is to cut down on the number of table lookups in
-- cfg.protectionCategories, which grows exponentially with the number of
-- non-nil keys. We keep track of the number of active subtables with the
-- noActive parameter.
--]]
local noActive, attemptOrder
do
local active, inactive = {}, {}
for i, t in ipairs(order) do
if t.val then
active[#active + 1] = t
else
inactive[#inactive + 1] = t
end
end
noActive = #active
attemptOrder = active
for i, t in ipairs(inactive) do
attemptOrder[#attemptOrder + 1] = t
end
end
--[[
-- Check increasingly generic key combinations until we find a match. If a
-- specific category exists for the combination of key fragments we are
-- given, that match will be found first. If not, we keep trying different
-- key fragment combinations until we match using the key
-- "all-all-all-all-all".
--
-- To generate the keys, we index the key subtables using a binary matrix
-- with indexes i and j. j is only calculated up to the number of active
-- subtables. For example, if there were three active subtables, the matrix
-- would look like this, with 0 corresponding to the key fragment "all", and
-- 1 corresponding to other key fragments.
--
-- j 1 2 3
-- i
-- 1 1 1 1
-- 2 0 1 1
-- 3 1 0 1
-- 4 0 0 1
-- 5 1 1 0
-- 6 0 1 0
-- 7 1 0 0
-- 8 0 0 0
--
-- Values of j higher than the number of active subtables are set
-- to the string "all".
--
-- A key for cfg.protectionCategories is constructed for each value of i.
-- The position of the value in the key is determined by the keypos field in
-- each subtable.
--]]
local cats = cfg.protectionCategories
for i = 1, 2^noActive do
local key = {}
for j, t in ipairs(attemptOrder) do
if j > noActive then
key[t.keypos] = 'all'
else
local quotient = i / 2 ^ (j - 1)
quotient = math.ceil(quotient)
if quotient % 2 == 1 then
key[t.keypos] = t.val
else
key[t.keypos] = 'all'
end
end
end
key = table.concat(key, '|')
local attempt = cats[key]
if attempt then
return makeCategoryLink(attempt, title.text)
end
end
return ''
end
function Protection:isIncorrect()
local expiry = self.expiry
return not self:isProtected()
or type(expiry) == 'number' and expiry < os.time()
end
function Protection:isTemplateProtectedNonTemplate()
local action, namespace = self.action, self.title.namespace
return self.level == 'templateeditor'
and (
(action ~= 'edit' and action ~= 'move')
or (namespace ~= 10 and namespace ~= 828)
)
end
function Protection:makeCategoryLinks()
local msg = self._cfg.msg
local ret = { self:makeProtectionCategory() }
if self:isIncorrect() then
ret[#ret + 1] = makeCategoryLink(
msg['tracking-category-incorrect'],
self.title.text
)
end
if self:isTemplateProtectedNonTemplate() then
ret[#ret + 1] = makeCategoryLink(
msg['tracking-category-template'],
self.title.text
)
end
return table.concat(ret)
end
--------------------------------------------------------------------------------
-- Blurb class
--------------------------------------------------------------------------------
local Blurb = {}
Blurb.__index = Blurb
Blurb.bannerTextFields = {
text = true,
explanation = true,
tooltip = true,
alt = true,
link = true
}
function Blurb.new(protectionObj, args, cfg)
return setmetatable({
_cfg = cfg,
_protectionObj = protectionObj,
_args = args
}, Blurb)
end
-- Private methods --
function Blurb:_formatDate(num)
-- Formats a Unix timestamp into dd Month, YYYY format.
lang = lang or mw.language.getContentLanguage()
local success, date = pcall(
lang.formatDate,
lang,
self._cfg.msg['expiry-date-format'] or 'j F Y',
'@' .. tostring(num)
)
if success then
return date
end
end
function Blurb:_getExpandedMessage(msgKey)
return self:_substituteParameters(self._cfg.msg[msgKey])
end
function Blurb:_substituteParameters(msg)
if not self._params then
local parameterFuncs = {}
parameterFuncs.CURRENTVERSION = self._makeCurrentVersionParameter
parameterFuncs.EDITREQUEST = self._makeEditRequestParameter
parameterFuncs.EXPIRY = self._makeExpiryParameter
parameterFuncs.EXPLANATIONBLURB = self._makeExplanationBlurbParameter
parameterFuncs.IMAGELINK = self._makeImageLinkParameter
parameterFuncs.INTROBLURB = self._makeIntroBlurbParameter
parameterFuncs.INTROFRAGMENT = self._makeIntroFragmentParameter
parameterFuncs.PAGETYPE = self._makePagetypeParameter
parameterFuncs.PROTECTIONBLURB = self._makeProtectionBlurbParameter
parameterFuncs.PROTECTIONDATE = self._makeProtectionDateParameter
parameterFuncs.PROTECTIONLEVEL = self._makeProtectionLevelParameter
parameterFuncs.PROTECTIONLOG = self._makeProtectionLogParameter
parameterFuncs.TALKPAGE = self._makeTalkPageParameter
parameterFuncs.TOOLTIPBLURB = self._makeTooltipBlurbParameter
parameterFuncs.TOOLTIPFRAGMENT = self._makeTooltipFragmentParameter
parameterFuncs.VANDAL = self._makeVandalTemplateParameter
self._params = setmetatable({}, {
__index = function (t, k)
local param
if parameterFuncs[k] then
param = parameterFuncs[k](self)
end
param = param or ''
t[k] = param
return param
end
})
end
msg = msg:gsub('${(%u+)}', self._params)
return msg
end
function Blurb:_makeCurrentVersionParameter()
-- A link to the page history or the move log, depending on the kind of
-- protection.
local pagename = self._protectionObj.title.prefixedText
if self._protectionObj.action == 'move' then
-- We need the move log link.
return makeFullUrl(
'Special:Log',
{type = 'move', page = pagename},
self:_getExpandedMessage('current-version-move-display')
)
else
-- We need the history link.
return makeFullUrl(
pagename,
{action = 'history'},
self:_getExpandedMessage('current-version-edit-display')
)
end
end
function Blurb:_makeEditRequestParameter()
local mEditRequest = require('Module:Submit an edit request')
local action = self._protectionObj.action
local level = self._protectionObj.level
-- Get the edit request type.
local requestType
if action == 'edit' then
if level == 'autoconfirmed' then
requestType = 'semi'
elseif level == 'extendedconfirmed' then
requestType = 'extended'
elseif level == 'templateeditor' then
requestType = 'template'
end
end
requestType = requestType or 'full'
-- Get the display value.
local display = self:_getExpandedMessage('edit-request-display')
return mEditRequest._link{type = requestType, display = display}
end
function Blurb:_makeExpiryParameter()
local expiry = self._protectionObj.expiry
if type(expiry) == 'number' then
return self:_formatDate(expiry)
else
return expiry
end
end
function Blurb:_makeExplanationBlurbParameter()
-- Cover special cases first.
if self._protectionObj.title.namespace == 8 then
-- MediaWiki namespace
return self:_getExpandedMessage('explanation-blurb-nounprotect')
end
-- Get explanation blurb table keys
local action = self._protectionObj.action
local level = self._protectionObj.level
local talkKey = self._protectionObj.title.isTalkPage and 'talk' or 'subject'
-- Find the message in the explanation blurb table and substitute any
-- parameters.
local explanations = self._cfg.explanationBlurbs
local msg
if explanations[action][level] and explanations[action][level][talkKey] then
msg = explanations[action][level][talkKey]
elseif explanations[action][level] and explanations[action][level].default then
msg = explanations[action][level].default
elseif explanations[action].default and explanations[action].default[talkKey] then
msg = explanations[action].default[talkKey]
elseif explanations[action].default and explanations[action].default.default then
msg = explanations[action].default.default
else
istalk = talkKey == 'talk' and true or false
error(string.format(
'找不到 action=%s protectionlevel=%s istalkpage=%s 時的解釋說明',
action,
level,
istalk
), 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeImageLinkParameter()
local imageLinks = self._cfg.imageLinks
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if imageLinks[action][level] then
msg = imageLinks[action][level]
elseif imageLinks[action].default then
msg = imageLinks[action].default
else
msg = imageLinks.edit.default
end
return self:_substituteParameters(msg)
end
function Blurb:_makeIntroBlurbParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('intro-blurb-expiry')
else
return self:_getExpandedMessage('intro-blurb-noexpiry')
end
end
function Blurb:_makeIntroFragmentParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('intro-fragment-expiry')
else
return self:_getExpandedMessage('intro-fragment-noexpiry')
end
end
function Blurb:_makePagetypeParameter()
local pagetypes = self._cfg.pagetypes
return pagetypes[self._protectionObj.title.namespace]
or pagetypes.default
or error('「pagetypes.default」丟失!', 8)
end
function Blurb:_makeProtectionBlurbParameter()
local protectionBlurbs = self._cfg.protectionBlurbs
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if protectionBlurbs[action][level] then
msg = protectionBlurbs[action][level]
elseif protectionBlurbs[action].default then
msg = protectionBlurbs[action].default
elseif protectionBlurbs.edit.default then
msg = protectionBlurbs.edit.default
else
error('沒有為「protectionBlurbs.edit.default」定義保護說明!', 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeProtectionDateParameter()
local protectionDate = self._protectionObj.protectionDate
if type(protectionDate) == 'number' then
return self:_formatDate(protectionDate)
else
return protectionDate
end
end
function Blurb:_makeProtectionLevelParameter()
local protectionLevels = self._cfg.protectionLevels
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if protectionLevels[action][level] then
msg = protectionLevels[action][level]
elseif protectionLevels[action].default then
msg = protectionLevels[action].default
elseif protectionLevels.edit.default then
msg = protectionLevels.edit.default
else
error('沒有為「protectionLevels.edit.default」定義保護級別!', 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeProtectionLogParameter()
local pagename = self._protectionObj.title.prefixedText
if self._protectionObj.action == 'autoreview' then
-- We need the pending changes log.
return makeFullUrl(
'Special:Log',
{type = 'stable', page = pagename},
self:_getExpandedMessage('pc-log-display')
)
else
-- We need the protection log.
return makeFullUrl(
'Special:Log',
{type = 'protect', page = pagename},
self:_getExpandedMessage('protection-log-display')
)
end
end
function Blurb:_makeTalkPageParameter()
return string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[self._protectionObj.title.namespace].talk.name,
self._protectionObj.title.text,
self._args.section or 'top',
self:_getExpandedMessage('talk-page-link-display')
)
end
function Blurb:_makeTooltipBlurbParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('tooltip-blurb-expiry')
else
return self:_getExpandedMessage('tooltip-blurb-noexpiry')
end
end
function Blurb:_makeTooltipFragmentParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('tooltip-fragment-expiry')
else
return self:_getExpandedMessage('tooltip-fragment-noexpiry')
end
end
function Blurb:_makeVandalTemplateParameter()
return require('Module:Vandal-m')._main{
self._args.user or self._protectionObj.title.baseText
}
end
-- Public methods --
function Blurb:makeBannerText(key)
-- Validate input.
if not key or not Blurb.bannerTextFields[key] then
error(string.format(
'「%s」不是有效的橫幅配置金鑰。',
tostring(key)
), 2)
end
-- Generate the text.
local msg = self._protectionObj.bannerConfig[key]
if type(msg) == 'string' then
return self:_substituteParameters(msg)
elseif type(msg) == 'function' then
msg = msg(self._protectionObj, self._args)
if type(msg) ~= 'string' then
error(string.format(
'解析橫幅配置時生成錯誤「%s」',
tostring(key),
type(msg)
), 4)
end
return self:_substituteParameters(msg)
end
end
--------------------------------------------------------------------------------
-- BannerTemplate class
--------------------------------------------------------------------------------
local BannerTemplate = {}
BannerTemplate.__index = BannerTemplate
function BannerTemplate.new(protectionObj, cfg)
local obj = {}
obj._cfg = cfg
-- Set the image filename.
local imageFilename = protectionObj.bannerConfig.image
if imageFilename then
obj._imageFilename = imageFilename
else
-- If an image filename isn't specified explicitly in the banner config,
-- generate it from the protection status and the namespace.
local action = protectionObj.action
local level = protectionObj.level
local namespace = protectionObj.title.namespace
local reason = protectionObj.reason
-- Deal with special cases first.
if (
namespace == 10
or namespace == 828
or reason and obj._cfg.indefImageReasons[reason]
)
and action == 'edit'
and level == 'sysop'
and not protectionObj:isTemporary()
then
-- Fully protected modules and templates get the special red "indef"
-- padlock.
obj._imageFilename = obj._cfg.msg['image-filename-indef']
else
-- Deal with regular protection types.
local images = obj._cfg.images
if images[action] then
if images[action][level] then
obj._imageFilename = images[action][level]
elseif images[action].default then
obj._imageFilename = images[action].default
end
end
end
end
return setmetatable(obj, BannerTemplate)
end
function BannerTemplate:renderImage()
local filename = self._imageFilename
or self._cfg.msg['image-filename-default']
or 'Transparent.gif'
return makeFileLink{
file = filename,
size = (self.imageWidth or 20) .. 'px',
alt = self._imageAlt,
link = self._imageLink,
caption = self.imageCaption
}
end
--------------------------------------------------------------------------------
-- Banner class
--------------------------------------------------------------------------------
local Banner = setmetatable({}, BannerTemplate)
Banner.__index = Banner
function Banner.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj.imageWidth = 40
obj.imageCaption = blurbObj:makeBannerText('alt') -- Large banners use the alt text for the tooltip.
obj._reasonText = blurbObj:makeBannerText('text')
obj._explanationText = blurbObj:makeBannerText('explanation')
obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing.
return setmetatable(obj, Banner)
end
function Banner:__tostring()
-- Renders the banner.
makeMessageBox = makeMessageBox or require('Module:Message box').main
local reasonText = self._reasonText or error('沒有理由!', 2)
local explanationText = self._explanationText
local mbargs = {
page = self._page,
type = 'protection',
image = self:renderImage(),
text = string.format(
"'''%s'''%s",
reasonText,
explanationText and '<br />' .. explanationText or ''
)
}
return makeMessageBox('mbox', mbargs)
end
--------------------------------------------------------------------------------
-- Padlock class
--------------------------------------------------------------------------------
local Padlock = setmetatable({}, BannerTemplate)
Padlock.__index = Padlock
function Padlock.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj.imageWidth = 20
obj.imageCaption = blurbObj:makeBannerText('tooltip')
obj._imageAlt = blurbObj:makeBannerText('alt')
obj._imageLink = blurbObj:makeBannerText('link')
obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action]
or cfg.padlockIndicatorNames.default
or 'pp-default'
return setmetatable(obj, Padlock)
end
function Padlock:__tostring()
local frame = mw.getCurrentFrame()
-- The nowiki tag helps prevent whitespace at the top of articles.
return frame:extensionTag{name = 'nowiki'} .. frame:extensionTag{
name = 'indicator',
args = {name = self._indicatorName},
content = self:renderImage()
}
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- This is used for testing purposes.
return {
Protection = Protection,
Blurb = Blurb,
BannerTemplate = BannerTemplate,
Banner = Banner,
Padlock = Padlock,
}
end
function p._main(args, cfg, title)
args = args or {}
cfg = cfg or require(CONFIG_MODULE)
local protectionObj = Protection.new(args, cfg, title)
local ret = {}
-- If a page's edit protection is equally or more restrictive than its
-- protection from some other action, then don't bother displaying anything
-- for the other action (except categories).
if protectionObj.action == 'edit' or
args.demolevel or
not getReachableNodes(
cfg.hierarchy,
protectionObj.level
)[effectiveProtectionLevel('edit', protectionObj.title)]
then
-- Initialise the blurb object
local blurbObj = Blurb.new(protectionObj, args, cfg)
-- Render the banner
if protectionObj:isProtected() then
ret[#ret + 1] = tostring(
(yesno(args.small) and Padlock or Banner)
.new(protectionObj, blurbObj, cfg)
)
end
end
-- Render the categories
if yesno(args.category) ~= false then
ret[#ret + 1] = protectionObj:makeCategoryLinks()
end
return table.concat(ret)
end
function p.main(frame, cfg)
cfg = cfg or require(CONFIG_MODULE)
-- Find default args, if any.
local parent = frame.getParent and frame:getParent()
local defaultArgs = parent and cfg.wrappers[parent:getTitle():gsub('/sandbox$', '')]
-- Find user args, and use the parent frame if we are being called from a
-- wrapper template.
getArgs = getArgs or require('Module:Arguments').getArgs
local userArgs = getArgs(frame, {
parentOnly = defaultArgs,
frameOnly = not defaultArgs
})
-- Build the args table. User-specified args overwrite default args.
local args = {}
for k, v in pairs(defaultArgs or {}) do
args[k] = v
end
for k, v in pairs(userArgs) do
args[k] = v
end
return p._main(args, cfg)
end
return p
0c5173a5a01ad7424318edf28b14b67825cc186a
Template:Namespace detect
10
267
556
2021-06-01T06:06:04Z
zhwp>Hamish
0
回退到由[[Special:Contributions/Hamish|Hamish]]([[User talk:Hamish|討論]])做出的修訂版本65887169:Per ep
wikitext
text/x-wiki
{{#switch:
{{lc: <!--Lower case the result-->
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{{demospace}}}
| {{#ifeq:{{NAMESPACE}}|{{ns:0}}
| main
| {{#ifeq:{{NAMESPACE}}|{{TALKSPACE}}
| talk
| {{NAMESPACE}}
}}
}}
}}
}}
| main = {{#switch:{{str mid|{{FULLPAGENAME}}||{{#expr:abs({{str find|{{FULLPAGENAME}}|:}})-1}}}}<!--
---->| MOS = {{{pseudo| {{{mos| {{{other|}}} }}} }}}<!--
---->| LTA = {{{pseudo| {{{lta| {{{other|}}} }}} }}}<!--
---->| NT = {{{pseudo| {{{nt| {{{other|}}} }}} }}}<!--
---->| NC = {{{pseudo| {{{nc| {{{other|}}} }}} }}}<!--
---->| #default = {{{main| {{{other|}}} }}}<!--
---->}}
| talk = {{{talk| {{{other|}}} }}}
| user = {{{user| {{{other|}}} }}}
| wikipedia = {{{wikipedia| {{{other|}}} }}}
| image = {{{image| {{{other|}}} }}}
| mediawiki = {{{mediawiki| {{{other|}}} }}}
| template = {{{template| {{{other|}}} }}}
| help = {{{help| {{{other|}}} }}}
| category = {{{category| {{{other|}}} }}}
| portal = {{{portal| {{{other|}}} }}}
| wikiproject = {{{wikiproject| {{{other|}}} }}}
| other
| #default = {{{other|}}}
}}<!--End switch--><noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, and interwikis to Wikidata. -->
</noinclude>
f1961a31d9c2e2c54d527eb6206563f5626ce288
Template:Category handler/blacklist
10
263
548
2021-06-06T15:03:53Z
zhwp>Manchiu
0
已保护“[[Template:Category handler/blacklist]]”:高风险模板([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<noinclude>'''Actual code of this blacklist:'''<pre></noinclude>{{if pagename
<!-- Start of blacklist -->
| Main Page = hide <!-- Don't categorise the main page -->
<!-- Don't categorise on centralised cascade page or its subpages -->
| Wikipedia:Cascade-protected items/+ = hide
<!-- Don't categorise userboxes in their own "template space" -->
| User:UBX/+ = hide
| User talk:UBX/+ = hide
| Wikipedia:Template messages/* = hide <!-- Don't categorise on its subpages -->
| /archiv* = hide <!-- Don't categorise on /archive pages -->
<!-- End of blacklist -->
| page = {{{page|}}} <!-- Never change this one, see the doc -->
}}<noinclude></pre>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
b152c913c7d6755273326ec0648587b9b18d2979
Template:Le
10
313
651
2021-06-23T00:05:12Z
zhwp>Xiplus-abot
0
已更改“[[Template:Le]]”的保护设定:高風險模板:100134引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/en]]
{{短名重定向}}
{{模板重定向}}
866c4d05848633090eb9763d9c480ebe2c6b4fdf
Template:Infobox person/height/locate
10
217
452
2021-08-05T11:19:24Z
zhwp>Sanmosa
0
回退[[Special:Contributions/Sanmosa|Sanmosa]]([[User talk:Sanmosa|對話]])的編輯:好像出錯了,先退回
wikitext
text/x-wiki
{{infobox person/height/switch
|{{{1|}}}
|{{#invoke:String|replace|{{{1|}}}| | }}
|m={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|m}}
|c={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|cm}}
|f={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|ft}}
|i={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|in}}
}}<noinclude>
{{Documentation}}
</noinclude>
159e634f03c95c6d6d1362ec46f6ed6e00c94478
Template:Infobox person/height/switch
10
218
454
2021-08-05T11:21:56Z
zhwp>Sanmosa
0
看看能不能出回中文單位 // Edit via Wikiplus
wikitext
text/x-wiki
{{#switch:0
|{{{m}}}{{{f}}}{{{i}}}={{{1|}}}
|{{{f}}}{{{i}}}={{#ifeq:{{{c}}}|0
|{{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{m|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{m|1}}}-1}}}}|m|ftin|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{m|1}}}+1}}}}
}}
|{{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{c|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{c|1}}}-1}}}}|cm|ftin|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{m|1}}}+1}}}}
}}
}}
|{{{m}}}{{{f}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{i|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{i|1}}}-1}}}}|in|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{i|1}}}+2}}}}
}}
|{{{m}}}{{{i}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}|ft|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}}}
}}
|{{{m}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}+{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}|{{#expr:{{{i|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}|ft|{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}|{{#expr:{{{i|1}}}-1}}}}|in|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{i|1}}}+2}}}}
}}
|{{{1|}}}
}}<noinclude>
{{Documentation}}
</noinclude>
ddea355ebb6ef35416734e310130e4ac27d50f21
Module:Hatnote list
828
80
154
2021-08-18T13:43:45Z
zhwp>蕭漫
0
[[那艺娜维基:互助客栈/技术#About_模板使用自定义文本后出现多余句号]](https://zh.wikipedia.org/w/index.php?title=那艺娜维基:%E4%BA%92%E5%8A%A9%E5%AE%A2%E6%A0%88/%E6%8A%80%E6%9C%AF&oldid=67189820)
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote list --
-- --
-- This module produces and formats lists for use in hatnotes. In particular, --
-- it implements the for-see list, i.e. lists of "For X, see Y" statements, --
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced --
-- are andList & orList helpers for formatting lists with those conjunctions. --
--------------------------------------------------------------------------------
local mArguments --initialize lazily
local mHatnote = require('Module:Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
--------------------------------------------------------------------------------
-- List stringification helper functions
--
-- These functions are used for stringifying lists, usually page lists inside
-- the "Y" portion of "For X, see Y" for-see items.
--------------------------------------------------------------------------------
--default options table used across the list stringification functions
-- 本地化注意
local stringifyListDefaultOptions = {
conjunction = "和",
separator = "、",
altSeparator = ";",
space = "",
formatted = false,
boldfaced = false,
quotes = false
}
-- Stringifies a list generically; probably shouldn't be used directly
function stringifyList(list, options)
-- Type-checks, defaults, and a shortcut
checkType("stringifyList", 1, list, "table")
if #list == 0 then return nil end
checkType("stringifyList", 2, options, "table", true)
options = options or {}
for k, v in pairs(stringifyListDefaultOptions) do
if options[k] == nil then options[k] = v end
end
local s = options.space
-- Format the list if requested
if options.formatted then list = mHatnote.formatPages(unpack(list)) end
-- Set the separator; if any item contains it, use the alternate separator
local separator = options.separator
--searches display text only
function searchDisp(t, f)
return string.find(string.sub(t, (string.find(t, '|') or 0) + 1), f)
end
for k, v in pairs(list) do
-- 本地化注意
if options.boldfaced then
list[k] = '\'\'\'' .. list[k] .. '\'\'\''
end
if options.quotes then
list[k] = '「' .. list[k] .. '」'
end
if searchDisp(v, separator) then
separator = options.altSeparator
break
end
end
-- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§"
local conjunction = s .. options.conjunction .. s
-- 本地化注意
-- separator .. conjunction的结果是“、和”
-- if #list == 2 and searchDisp(list[1], "§") or #list > 2 then
-- conjunction = separator .. conjunction
-- end
-- Return the formatted string
return mw.text.listToText(list, separator .. s, conjunction)
end
--DRY function
-- 本地化注意
function conjList (conj, list, fmt, bold, quo)
return stringifyList(list, {conjunction = conj, formatted = fmt, boldfaced = bold, quotes=quo})
end
-- Stringifies lists with "and" or "or"
-- 本地化注意
function p.andList (...) return conjList("和", ...) end
function p.orList (...) return conjList("或", ...) end
--------------------------------------------------------------------------------
-- For see
--
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the
-- {{about}} and {{redirect}} templates and their variants.
--------------------------------------------------------------------------------
--default options table used across the forSee family of functions
-- 本地化注意
local forSeeDefaultOptions = {
andKeyword = '和',
title = mw.title.getCurrentTitle().text,
otherText = '其他用法',
forSeeForm = '关于%s,请见%s。',
}
--Collapses duplicate punctuation
-- 本地化注意
function punctuationCollapse (text)
local replacements = {
["%.%.$"] = ".",
["%?%.$"] = "?",
["%!%.$"] = "!",
["%.%]%]%.$"] = ".]]",
["%?%]%]%.$"] = "?]]",
["%!%]%]%.$"] = "!]]",
["%。%。$"] = "。",
["%?%。$"] = "?",
["%!%。$"] = "!",
["%。%]%]%。$"] = "。]]",
["%?%]%]%。$"] = "?]]",
["%!%]%]%。$"] = "!]]"
}
for k, v in pairs(replacements) do text = string.gsub(text, k, v) end
return text
end
-- Structures arguments into a table for stringification, & options
function p.forSeeArgsToTable (args, from, options)
-- Type-checks and defaults
checkType("forSeeArgsToTable", 1, args, 'table')
checkType("forSeeArgsToTable", 2, from, 'number', true)
from = from or 1
checkType("forSeeArgsToTable", 3, options, 'table', true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- maxArg's gotten manually because getArgs() and table.maxn aren't friends
local maxArg = 0
for k, v in pairs(args) do
if type(k) == 'number' and k > maxArg then maxArg = k end
end
-- Structure the data out from the parameter list:
-- * forTable is the wrapper table, with forRow rows
-- * Rows are tables of a "use" string & a "pages" table of pagename strings
-- * Blanks are left empty for defaulting elsewhere, but can terminate list
local forTable = {}
local i = from
local terminated = false
-- If there is extra text, and no arguments are given, give nil value
-- to not produce default of "For other uses, see foo (disambiguation)"
if options.extratext and i > maxArg then return nil end
-- Loop to generate rows
repeat
-- New empty row
local forRow = {}
-- On blank use, assume list's ended & break at end of this loop
forRow.use = args[i]
if not args[i] then terminated = true end
-- New empty list of pages
forRow.pages = {}
-- Insert first pages item if present
table.insert(forRow.pages, args[i + 1])
-- If the param after next is "and", do inner loop to collect params
-- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3}
while args[i + 2] == options.andKeyword do
if args[i + 3] then
table.insert(forRow.pages, args[i + 3])
end
-- Increment to next "and"
i = i + 2
end
-- Increment to next use
i = i + 2
-- Append the row
table.insert(forTable, forRow)
until terminated or i > maxArg
return forTable
end
-- Stringifies a table as formatted by forSeeArgsToTable
function p.forSeeTableToString (forSeeTable, options)
-- Type-checks and defaults
checkType("forSeeTableToString", 1, forSeeTable, "table", true)
checkType("forSeeTableToString", 2, options, "table", true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Stringify each for-see item into a list
local strList = {}
if forSeeTable then
for k, v in pairs(forSeeTable) do
local useStr = v.use or options.otherText
-- 本地化注意
local pagesStr = p.andList(v.pages, true, true, true) or '「\'\'\'' .. mHatnote._formatLink(mHatnote.disambiguate(options.title)) .. '\'\'\'」'
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)
forSeeStr = punctuationCollapse(forSeeStr)
table.insert(strList, forSeeStr)
end
end
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'。')) end
-- Return the concatenated list
return table.concat(strList)
end
-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps
-- but not blank/whitespace values. Ignores named args and args < "from".
function p._forSee (args, from, options)
local forSeeTable = p.forSeeArgsToTable(args, from, options)
return p.forSeeTableToString(forSeeTable, options)
end
-- As _forSee, but uses the frame.
function p.forSee (frame, from, options)
mArguments = require('Module:Arguments')
return p._forSee(mArguments.getArgs(frame), from, options)
end
return p
38feee2afbc1ce641c952305addbbea4f726544a
Module:Effective protection level
828
62
118
2021-08-24T18:03:16Z
zhwp>Jimmy Xu
0
ep from enwiki r980896975
Scribunto
text/plain
local p = {}
-- Returns the permission required to perform a given action on a given title.
-- If no title is specified, the title of the page being displayed is used.
function p._main(action, pagename)
local title
if type(pagename) == 'table' and pagename.prefixedText then
title = pagename
elseif pagename then
title = mw.title.new(pagename)
else
title = mw.title.getCurrentTitle()
end
pagename = title.prefixedText
if action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' and action ~= 'undelete' then
error( 'First parameter must be one of edit, move, create, upload, undelete', 2 )
end
if title.namespace == 8 then -- MediaWiki namespace
if title.text:sub(-3) == '.js' or title.text:sub(-4) == '.css' or title.contentModel == 'javascript' or title.contentModel == 'css' then -- site JS or CSS page
return 'interfaceadmin'
else -- any non-JS/CSS MediaWiki page
return 'sysop'
end
elseif title.namespace == 2 and title.isSubpage then
if title.contentModel == 'javascript' or title.contentModel == 'css' then -- user JS or CSS page
return 'interfaceadmin'
elseif title.contentModel == 'json' then -- user JSON page
return 'sysop'
end
end
if action == 'undelete' then
return 'sysop'
end
local level = title.protectionLevels[action] and title.protectionLevels[action][1]
if level == 'sysop' or level == 'editprotected' then
return 'sysop'
elseif title.cascadingProtection.restrictions[action] and title.cascadingProtection.restrictions[action][1] then -- used by a cascading-protected page
return 'sysop'
elseif level == 'templateeditor' then
return 'templateeditor'
elseif action == 'move' then
local blacklistentry = mw.ext.TitleBlacklist.test('edit', pagename) -- Testing action edit is correct, since this is for the source page. The target page name gets tested with action move.
if blacklistentry and not blacklistentry.params.autoconfirmed then
return 'sysop'
elseif title.namespace == 6 then
return 'filemover'
elseif level == 'extendedconfirmed' then
return 'extendedconfirmed'
else
return 'autoconfirmed'
end
end
local blacklistentry = mw.ext.TitleBlacklist.test(action, pagename)
if blacklistentry then
if not blacklistentry.params.autoconfirmed then
return 'sysop'
elseif level == 'extendedconfirmed' then
return 'extendedconfirmed'
else
return 'autoconfirmed'
end
elseif level == 'editsemiprotected' then -- create-semiprotected pages return this for some reason
return 'autoconfirmed'
elseif level then
return level
elseif action == 'upload' then
return 'autoconfirmed'
else
return '*'
end
end
setmetatable(p, { __index = function(t, k)
return function(frame)
return t._main(k, frame.args[1])
end
end })
return p
d22097a8a4da3e18514a12fbe2c417c4f4be91f2
Module:Citation/CS1/Date validation
828
178
362
2021-09-13T05:01:55Z
zhwp>Antigng
0
ep: [[Special:Diff/67678426]]
Scribunto
text/plain
local p = {}
--[[--------------------------< I S _ V A L I D _ D A T E _ F R O M _ A _ P O I N T >-------------------------
将日期验证的逻辑拆分出来,供其它模块使用
]]
local function is_valid_date_from_a_point (date, point_ts)
local lang = mw.getContentLanguage();
local good1, good2;
local access_ts, tomorrow_ts; -- to hold unix time stamps representing the dates
good1, access_ts = pcall( lang.formatDate, lang, 'U', date ); -- convert date value to unix timesatmp
good2, tomorrow_ts = pcall( lang.formatDate, lang, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then
access_ts = tonumber (access_ts); -- convert to numbers for the comparison
tomorrow_ts = tonumber (tomorrow_ts);
else
return false; -- one or both failed to convert to unix time stamp
end
if point_ts <= access_ts and access_ts < tomorrow_ts then -- the point <= date < tomorrow's date
return true;
else
return false; -- date out of range
end
end
--[[--------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
returns true if:
Wikipedia start date <= accessdate < today + 2 days
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)
accessdate is the date provided in |accessdate= at time 00:00:00 UTC
today is the current date at time 00:00:00 UTC plus 48 hours
if today is 2015-01-01T00:00:00 then
adding 24 hours gives 2015-01-02T00:00:00 – one second more than today
adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow
]]
local function is_valid_accessdate (accessdate)
accessdate = accessdate:gsub("年", "-");
accessdate = accessdate:gsub("月", "-");
accessdate = accessdate:gsub("日", "-");
accessdate = accessdate:gsub("-$", "");
return is_valid_date_from_a_point (accessdate, 979516800);
end
--[[--------------------------< G E T _ M O N T H _ N U M B E R >----------------------------------------------
returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0
]]
local function get_month_number (month)
local long_months = {['January']=1, ['February']=2, ['March']=3, ['April']=4, ['May']=5, ['June']=6, ['July']=7, ['August']=8, ['September']=9, ['October']=10, ['November']=11, ['December']=12};
local short_months = {['Jan']=1, ['Feb']=2, ['Mar']=3, ['Apr']=4, ['May']=5, ['Jun']=6, ['Jul']=7, ['Aug']=8, ['Sep']=9, ['Oct']=10, ['Nov']=11, ['Dec']=12};
local zh_months = {['1月']=1, ['2月']=2, ['3月']=3, ['4月']=4, ['5月']=5, ['6月']=6, ['7月']=7, ['8月']=8, ['9月']=9, ['10月']=10, ['11月']=11, ['12月']=12}; -- LOCAL
local temp;
temp=long_months[month];
if temp then return temp; end -- if month is the long-form name
temp=short_months[month];
if temp then return temp; end -- if month is the short-form name
temp=zh_months[month]; -- LOCAL
if temp then return temp; end -- if month is in Chinese -- LOCAL
return 0; -- misspelled, improper case, or not a month name
end
--[[--------------------------< G E T _ S E A S O N _ N U M B E R >--------------------------------------------
returns a number according to the sequence of seasons in a year: 1 for Winter, etc. Capitalization and spelling must be correct. If not a valid season, returns 0
]]
local function get_season_number (season)
local season_list = {['Winter']=21, ['Spring']=22, ['Summer']=23, ['Fall']=24, ['Autumn']=24}; -- make sure these numbers do not overlap month numbers
local temp;
temp=season_list[season];
if temp then return temp; end -- if season is a valid name return its number
return 0; -- misspelled, improper case, or not a season name
end
--[[--------------------------< I S _ P R O P E R _ N A M E >--------------------------------------------------
returns a non-zero number if date contains a recognized proper name. Capitalization and spelling must be correct.
]]
local function is_proper_name (name)
local name_list = {['Christmas']=31}
local temp;
temp=name_list[name];
if temp then return temp; end -- if name is a valid name return its number
return 0; -- misspelled, improper case, or not a proper name
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ O R _ S E A S O N >------------------------------
--returns true if month or season is valid (properly spelled, capitalized, abbreviated)
]]
local function is_valid_month_or_season (month_season)
if 0 == get_month_number (month_season) then -- if month text isn't one of the twelve months, might be a season
if 0 == get_season_number (month_season) then -- not a month, is it a season?
return false; -- return false not a month or one of the five seasons
end
end
return true;
end
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
Function gets current year from the server and compares it to year from a citation parameter. Years more than one year in the future are not acceptable.
]]
local function is_valid_year(year)
if not is_set(year_limit) then
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once
end
return tonumber(year) <= year_limit; -- false if year is in the future more than one year
end
--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------
Returns true if day is less than or equal to the number of days in month and year is no farther into the future
than next year; else returns false.
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately
1923) dates are assumed to be Gregorian.
]]
local function is_valid_date (year, month, day)
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
if not is_valid_year(year) then -- no farther into the future than next year
return false;
end
month = tonumber(month); -- required for YYYY-MM-DD dates
if (2==month) then -- if February
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0==(year%4) then
month_length = 29;
end
else -- Gregorian calendar
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
end
else
month_length=days_in_month[month];
end
if tonumber (day) > month_length then
return false;
end
return true;
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >--------------------------
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August.
There is a special test for May because it can be either short or long form.
Returns true when style for both months is the same
]]
local function is_valid_month_range_style (month1, month2)
local len1 = month1:len();
local len2 = month2:len();
if len1 == len2 then
return true; -- both months are short form so return true
elseif 'May' == month1 or 'May'== month2 then
return true; -- both months are long form so return true
elseif 3 == len1 or 3 == len2 then
return false; -- months are mixed form so return false
else
return true; -- both months are long form so return true
end
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------
Check a pair of months or seasons to see if both are valid members of a month or season pair.
Month pairs are expected to be left to right, earliest to latest in time.
Similarly, seasons are also left to right, earliest to latest in time. There is an oddity with seasons: winter is assigned a value of 1, spring 2, ...,
fall and autumn 4. Because winter can follow fall/autumn at the end of a calender year, a special test is made to see if |date=Fall-Winter yyyy (4-1) is the date.
]]
local function is_valid_month_season_range(range_start, range_end)
local range_start_number = get_month_number (range_start);
if 0 == range_start_number then -- is this a month range?
local range_start_number = get_season_number (range_start); -- not a month; is it a season? get start season number
local range_end_number = get_season_number (range_end); -- get end season number
if 0 ~= range_start_number then -- is start of range a season?
if range_start_number < range_end_number then -- range_start is a season
return true; -- return true when range_end is also a season and follows start season; else false
end
if 24 == range_start_number and 21 == range_end_number then -- special case when season range is Fall-Winter or Autumn-Winter
return true;
end
end
return false; -- range_start is not a month or a season; or range_start is a season and range_end is not; or improper season sequence
end
local range_end_number = get_month_number (range_end); -- get end month number
if range_start_number < range_end_number then -- range_start is a month; does range_start precede range_end?
if is_valid_month_range_style (range_start, range_end) then -- do months have the same style?
return true; -- proper order and same style
end
end
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month
end
--[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------
This function receives a table of date parts for one or two dates and an empty table reference declared in
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is
determined to be a valid date format. The question of what to do with invalid date formats is not answered here.
The date parts in the input table are converted to an ISO 8601 conforming date string:
single whole dates: yyyy-mm-dd
month and year dates: yyyy-mm
year dates: yyyy
ranges: yyyy-mm-dd/yyyy-mm-dd
yyyy-mm/yyyy-mm
yyyy/yyyy
Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from
Julian to Proleptic Gregorian.
The input table has:
year, year2 – always present; if before 1582, ignore months and days if present
month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 31– proper name dates
day, day2 – 0 if not provided, 1-31 for days
the output table receives:
rftdate: an IS8601 formatted date
rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and propername dates)
rftssn: one of four season keywords: winter, spring, summer, fall (lowercase)
]]
local function make_COinS_date (input, tCOinS_date)
local date; -- one date or first date in a range
local date2 = ''; -- end of range date
if 1582 > tonumber(input.year) or 20 < tonumber(input.month) then -- Julian calendar or season so &rft.date gets year only
date = input.year;
if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year
date = string.format ('%.4d/%.4d', tonumber(input.year), tonumber(input.year2)) -- assemble the date range
end
if 20 < tonumber(input.month) then -- if season or propername date
local season = {[21]='winter', [22]='spring', [23]='summer', [24]='fall', [31]='Christmas'}; -- seasons lowercase, no autumn; proper names use title case
if 0 == input.month2 then -- single season date
if 30 <tonumber(input.month) then
tCOinS_date.rftchron = season[input.month]; -- proper name dates
else
tCOinS_date.rftssn = season[input.month]; -- seasons
end
else -- season range with a second season specified
if input.year ~= input.year2 then -- season year – season year range or season year–year
tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
if 0~= month2 then
tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2);
end
else -- season–season year range
tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
tCOinS_date.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range
end
end
end
tCOinS_date.rftdate = date;
return; -- done
end
if 0 ~= input.day then
date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date
elseif 0 ~= input.month then
date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month
else
date = string.format ('%s', input.year); -- just year
end
if 0 ~= input.year2 then
if 0 ~= input.day2 then
date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date
elseif 0 ~= input.month2 then
date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month
else
date2 = string.format ('/%s', input.year2); -- just year
end
end
tCOinS_date.rftdate = date .. date2; -- date2 has the '/' separator
return;
end
--[[--------------------------< C H E C K _ D A T E >----------------------------------------------------------
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only
allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day
months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons
must be spelled correctly. Future years beyond next year are not allowed.
If the date fails the format tests, this function returns false and does not return values for anchor_year and
COinS_date. When this happens, the date parameter is used in the COinS metadata and the CITEREF identifier gets
its year from the year parameter if present otherwise CITEREF does not get a date value.
Inputs:
date_string - date string from date-holding parameters (date, year, accessdate, embargo, archivedate, etc.)
Returns:
false if date string is not a real date; else
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is ISO 8601 format date; see make_COInS_date()
]]
local function check_date (date_string, tCOinS_date)
local year; -- assume that year2, months, and days are not used;
local year2=0; -- second year in a year range
local month=0;
local month2=0; -- second month in a month range
local day=0;
local day2=0; -- second day in a day range
local anchor_year;
local coins_date;
if date_string:match("^%d%d%d%d%-%d%d%-%d%d$") then -- year-initial numerical year month day format
year, month, day=string.match(date_string, "(%d%d%d%d)%-(%d%d)%-(%d%d)");
if 12 < tonumber(month) or 1 > tonumber(month) or 1583 > tonumber(year) then return false; end -- month number not valid or not Gregorian calendar
anchor_year = year;
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial: month day, year
month, day, anchor_year, year=string.match(date_string, "(%a+)%s*(%d%d?),%s*((%d%d%d%d)%a?)");
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif date_string:match("^%a+ +[1-9]%d?–[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial day range: month day–day, year; days are separated by endash
month, day, day2, anchor_year, year=string.match(date_string, "(%a+) +(%d%d?)–(%d%d?), +((%d%d%d%d)%a?)");
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-initial: day month year
day, month, anchor_year, year=string.match(date_string, "(%d%d*)%s*(%a+)%s*((%d%d%d%d)%a?)");
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif date_string:match("^[1-9]%d?–[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-range-initial: day–day month year; days are separated by endash
day, day2, month, anchor_year, year=string.match(date_string, "(%d%d?)–(%d%d?) +(%a+) +((%d%d%d%d)%a?)");
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ – [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-range: day month - day month year; uses spaced endash
day, month, day2, month2, anchor_year, year=date_string:match("(%d%d?) +(%a+) – (%d%d?) +(%a+) +((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later;
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2=year;
elseif date_string:match("^%a+ +[1-9]%d? – %a+ +[1-9]%d?, +[1-9]%d%d%d?%a?$") then -- month initial month-day-range: month day – month day, year; uses spaced endash
month, day, month2, day2, anchor_year, year=date_string:match("(%a+) +(%d%d?) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d – [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
day, month, year, day2, month2, anchor_year, year2=date_string:match("(%d%d?) +(%a+) +(%d%d%d%d?) – (%d%d?) +(%a+) +((%d%d%d%d?)%a?)");
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d – %a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
month, day, year, month2, day2, anchor_year, year2=date_string:match("(%a+) +(%d%d?), +(%d%d%d%d) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)");
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
elseif date_string:match("^%a+ +[1-9]%d%d%d–%d%d%a?$") then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
local century;
month, year, century, anchor_year, year2=date_string:match("(%a+) +((%d%d)%d%d)–((%d%d)%a?)");
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
year2 = century..year2; -- add the century to year2 for comparisons
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number (month);
elseif date_string:match("^%a+ +[1-9]%d%d%d–[1-9]%d%d%d%a?$") then -- special case Winter/Summer year-year; year separated with unspaced endash
month, year, anchor_year, year2=date_string:match("(%a+) +(%d%d%d%d)–((%d%d%d%d)%a?)");
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number (month); -- for metadata
elseif date_string:match("^%a+ +[1-9]%d%d%d% – %a+ +[1-9]%d%d%d%a?$") then -- month/season year - month/season year; separated by spaced endash
month, year, month2, anchor_year, year2=date_string:match("(%a+) +(%d%d%d%d) – (%a+) +((%d%d%d%d)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style
month = get_month_number(month);
month2 = get_month_number(month2);
elseif 0 ~= get_season_number(month) and 0 ~= get_season_number(month2) then -- both must be or season year, not mixed
month = get_season_number(month);
month2 = get_season_number(month2);
else
return false;
end
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then -- month/season range year; months separated by endash
month, month2, anchor_year, year=date_string:match ("(%a+)–(%a+)%s*((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or (not is_valid_year(year)) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
month2 = get_month_number(month2);
else
month = get_season_number(month);
month2 = get_season_number(month2);
end
year2=year;
elseif date_string:match("^%a+ +%d%d%d%d%a?$") then -- month/season year or proper-name year
month, anchor_year, year=date_string:match("(%a+)%s*((%d%d%d%d)%a?)");
if not is_valid_year(year) then return false; end
if not is_valid_month_or_season (month) and 0 == is_proper_name (month) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
elseif 0 ~= get_season_number(month) then
month = get_season_number(month);
else
month = is_proper_name (month); -- must be proper name; not supported in COinS
end
elseif date_string:match("^[1-9]%d%d%d?–[1-9]%d%d%d?%a?$") then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
year, anchor_year, year2=date_string:match("(%d%d%d%d?)–((%d%d%d%d?)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif date_string:match("^[1-9]%d%d%d–%d%d%a?$") then -- Year range: YYYY–YY; separated by unspaced endash
local century;
year, century, anchor_year, year2=date_string:match("((%d%d)%d%d)–((%d%d)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor year from both years
if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003
year2 = century..year2; -- add the century to year2 for comparisons
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif date_string:match("^[1-9]%d%d%d?%a?$") then -- year; here accept either YYY or YYYY
anchor_year, year=date_string:match("((%d%d%d%d?)%a?)");
if false == is_valid_year(year) then
return false;
end
-- LOCAL: do not use mw.ustring: it allows full-width characters for %d.
elseif date_string:match("^[1-9]%d%d%d年[1-9]%d?月[1-9]%d?日$") then -- zh: year month day
year, month, day=date_string:match("(%d%d%d%d)年(%d%d*月)(%d%d*)日");
month = get_month_number (month);
if 0 == month then return false; end
anchor_year = year;
elseif date_string:match("^[1-9]%d%d%d年[1-9]%d?月$") then -- zh: year month
year, month=date_string:match("(%d%d%d%d)年(%d%d*月)");
month = get_month_number (month);
if 0 == month then return false; end
anchor_year = year;
elseif date_string:match("^[1-9]%d%d%d?年$") then -- zh: year; here accept either YYY or YYYY
year=date_string:match("(%d%d%d%d?)年");
if false == is_valid_year(year) then
return false;
end
anchor_year = year;
elseif date_string:match("^%d%d%d%d%-%d%d$") then -- numerical year month format
year, month=date_string:match("(%d%d%d%d)%-(%d%d)");
month=tonumber(month);
if 12 < month or 1 > month or 1583 > tonumber(year) then return false; end -- month number not valid or not Gregorian calendar
anchor_year = year;
-- END LOCAL
else
return false; -- date format not one of the MOS:DATE approved formats
end
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date)
result=is_valid_date(year,month,day);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year,month,day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year,month2,day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year2,month2,day2);
end
if false == result then return false; end
if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values
make_COinS_date ({year=year, month=month, day=day, year2=year2, month2=month2, day2=day2}, tCOinS_date); -- make an ISO 8601 date string for COinS
end
return true, anchor_year; -- format is good and date string represents a real date
end
--[[--------------------------< D A T E S >--------------------------------------------------------------------
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns
true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in
the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes).
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,
a single error message is created as the dates are tested.
]]
local function dates(date_parameters_list, tCOinS_date)
local anchor_year; -- will return as nil if the date being tested is not |date=
local COinS_date; -- will return as nil if the date being tested is not |date=
local error_message = "";
local good_date = false;
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v) then -- if the parameter has a value
if v:match("^c%. [1-9]%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
local year = v:match("c%. ([1-9]%d%d%d?)%a?"); -- get the year portion so it can be tested
if 'date'==k then
anchor_year, COinS_date = v:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter
good_date = is_valid_year(year);
elseif 'year'==k then
good_date = is_valid_year(year);
end
elseif 'date'==k then -- if the parameter is |date=
if v:match("^n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; no error when date parameter is set to no date
elseif v:match("^nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date
else
good_date, anchor_year, COinS_date = check_date (v, tCOinS_date); -- go test the date
end
elseif 'access-date'==k then -- if the parameter is |date=
good_date = check_date (v); -- go test the date
if true == good_date then -- if the date is a valid date
good_date = is_valid_accessdate (v); -- is Wikipedia start date < accessdate < tomorrow's date?
end
else -- any other date-holding parameter
good_date = check_date (v); -- go test the date
end
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "|" .. k .. "="; -- add the failed parameter
end
end
end
return anchor_year, error_message; -- and done
end
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------
Compare the value provided in |year= with the year value(s) provided in |date=. This function returns a numeric value:
0 - year value does not match the year value in date
1 - (default) year value matches the year value in date or one of the year values when date contains two years
2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)
]]
local function year_date_check (year_string, date_string)
local year;
local date1;
local date2;
local result = 1; -- result of the test; assume that the test passes
year = year_string:match ('(%d%d%d%d?)');
if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then --special case where date and year required YYYY-MM-DD and YYYYx
date1 = date_string:match ('(%d%d%d%d)');
year = year_string:match ('(%d%d%d%d)');
if year ~= date1 then
result = 0; -- years don't match
else
result = 2; -- years match; but because disambiguated, don't add to maint cat
end
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard formats of date with two three- or four-digit years
date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)");
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d[%s%-–]+%d%d") then -- YYYY-YY date ranges
local century;
date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)");
date2 = century..date2; -- convert YY to YYYY
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year
date1 = date_string:match ("(%d%d%d%d?)");
if year ~= date1 then
result = 0;
end
end
return result;
end
return {dates = dates, year_date_check = year_date_check, is_valid_date_from_a_point = is_valid_date_from_a_point}
-- return exported functions
ed984e5750e25e443f23ede2446e5932e2e0d0a4
那艺娜维基:Shortcut
4
19
33
2021-10-26T02:54:33Z
zhwp>LuciferianThomas
0
回退[[Special:Contributions/LuciferianThomas|LuciferianThomas]]([[User talk:LuciferianThomas|对话]])的编辑,改回[[Special:Contributions/Easterlies|Easterlies]]的最后一个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>{{Documentation}}</noinclude>
366b7fa8a7ebad556d8ab80288b32d97172cef80
Template:Shortcut
10
45
83
2021-10-26T02:54:33Z
zhwp>LuciferianThomas
0
回退[[Special:Contributions/LuciferianThomas|LuciferianThomas]]([[User talk:LuciferianThomas|对话]])的编辑,改回[[Special:Contributions/Easterlies|Easterlies]]的最后一个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>{{Documentation}}</noinclude>
366b7fa8a7ebad556d8ab80288b32d97172cef80
Module:Date
828
228
475
2021-11-18T00:05:12Z
zhwp>Xiplus-abot
0
已更改“[[Module:Date]]”的保护设置:高風險模板:100008引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
-- Date functions for use by other modules.
-- I18N and time zones are not supported.
local MINUS = '−' -- Unicode U+2212 MINUS SIGN
local floor = math.floor
local Date, DateDiff, diffmt -- forward declarations
local uniq = { 'unique identifier' }
local function is_date(t)
-- The system used to make a date read-only means there is no unique
-- metatable that is conveniently accessible to check.
return type(t) == 'table' and t._id == uniq
end
local function is_diff(t)
return type(t) == 'table' and getmetatable(t) == diffmt
end
local function _list_join(list, sep)
return table.concat(list, sep)
end
local function collection()
-- Return a table to hold items.
return {
n = 0,
add = function (self, item)
self.n = self.n + 1
self[self.n] = item
end,
join = _list_join,
}
end
local function strip_to_nil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (convenient when Date fields are provided from
-- another module which may pass a string, a number, or another type).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local function is_leap_year(year, calname)
-- Return true if year is a leap year.
if calname == 'Julian' then
return year % 4 == 0
end
return (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0
end
local function days_in_month(year, month, calname)
-- Return number of days (1..31) in given month (1..12).
if month == 2 and is_leap_year(year, calname) then
return 29
end
return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month]
end
local function h_m_s(time)
-- Return hour, minute, second extracted from fraction of a day.
time = floor(time * 24 * 3600 + 0.5) -- number of seconds
local second = time % 60
time = floor(time / 60)
return floor(time / 60), time % 60, second
end
local function hms(date)
-- Return fraction of a day from date's time, where (0 <= fraction < 1)
-- if the values are valid, but could be anything if outside range.
return (date.hour + (date.minute + date.second / 60) / 60) / 24
end
local function julian_date(date)
-- Return jd, jdz from a Julian or Gregorian calendar date where
-- jd = Julian date and its fractional part is zero at noon
-- jdz = same, but assume time is 00:00:00 if no time given
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- Testing shows this works for all dates from year -9999 to 9999!
-- JDN 0 is the 24-hour period starting at noon UTC on Monday
-- 1 January 4713 BC = (-4712, 1, 1) Julian calendar
-- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar
local offset
local a = floor((14 - date.month)/12)
local y = date.year + 4800 - a
if date.calendar == 'Julian' then
offset = floor(y/4) - 32083
else
offset = floor(y/4) - floor(y/100) + floor(y/400) - 32045
end
local m = date.month + 12*a - 3
local jd = date.day + floor((153*m + 2)/5) + 365*y + offset
if date.hastime then
jd = jd + hms(date) - 0.5
return jd, jd
end
return jd, jd - 0.5
end
local function set_date_from_jd(date)
-- Set the fields of table date from its Julian date field.
-- Return true if date is valid.
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- This handles the proleptic Julian and Gregorian calendars.
-- Negative Julian dates are not defined but they work.
local calname = date.calendar
local low, high -- min/max limits for date ranges −9999-01-01 to 9999-12-31
if calname == 'Gregorian' then
low, high = -1930999.5, 5373484.49999
elseif calname == 'Julian' then
low, high = -1931076.5, 5373557.49999
else
return
end
local jd = date.jd
if not (type(jd) == 'number' and low <= jd and jd <= high) then
return
end
local jdn = floor(jd)
if date.hastime then
local time = jd - jdn -- 0 <= time < 1
if time >= 0.5 then -- if at or after midnight of next day
jdn = jdn + 1
time = time - 0.5
else
time = time + 0.5
end
date.hour, date.minute, date.second = h_m_s(time)
else
date.second = 0
date.minute = 0
date.hour = 0
end
local b, c
if calname == 'Julian' then
b = 0
c = jdn + 32082
else -- Gregorian
local a = jdn + 32044
b = floor((4*a + 3)/146097)
c = a - floor(146097*b/4)
end
local d = floor((4*c + 3)/1461)
local e = c - floor(1461*d/4)
local m = floor((5*e + 2)/153)
date.day = e - floor((153*m + 2)/5) + 1
date.month = m + 3 - 12*floor(m/10)
date.year = 100*b + d - 4800 + floor(m/10)
return true
end
local function fix_numbers(numbers, y, m, d, H, M, S, partial, hastime, calendar)
-- Put the result of normalizing the given values in table numbers.
-- The result will have valid m, d values if y is valid; caller checks y.
-- The logic of PHP mktime is followed where m or d can be zero to mean
-- the previous unit, and -1 is the one before that, etc.
-- Positive values carry forward.
local date
if not (1 <= m and m <= 12) then
date = Date(y, 1, 1)
if not date then return end
date = date + ((m - 1) .. 'm')
y, m = date.year, date.month
end
local days_hms
if not partial then
if hastime and H and M and S then
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
days_hms = hms({ hour = H, minute = M, second = S })
end
end
if days_hms or not (1 <= d and d <= days_in_month(y, m, calendar)) then
date = date or Date(y, m, 1)
if not date then return end
date = date + (d - 1 + (days_hms or 0))
y, m, d = date.year, date.month, date.day
if days_hms then
H, M, S = date.hour, date.minute, date.second
end
end
end
numbers.year = y
numbers.month = m
numbers.day = d
if days_hms then
-- Don't set H unless it was valid because a valid H will set hastime.
numbers.hour = H
numbers.minute = M
numbers.second = S
end
end
local function set_date_from_numbers(date, numbers, options)
-- Set the fields of table date from numeric values.
-- Return true if date is valid.
if type(numbers) ~= 'table' then
return
end
local y = numbers.year or date.year
local m = numbers.month or date.month
local d = numbers.day or date.day
local H = numbers.hour
local M = numbers.minute or date.minute or 0
local S = numbers.second or date.second or 0
local need_fix
if y and m and d then
date.partial = nil
if not (-9999 <= y and y <= 9999 and
1 <= m and m <= 12 and
1 <= d and d <= days_in_month(y, m, date.calendar)) then
if not date.want_fix then
return
end
need_fix = true
end
elseif y and date.partial then
if d or not (-9999 <= y and y <= 9999) then
return
end
if m and not (1 <= m and m <= 12) then
if not date.want_fix then
return
end
need_fix = true
end
else
return
end
if date.partial then
H = nil -- ignore any time
M = nil
S = nil
else
if H then
-- It is not possible to set M or S without also setting H.
date.hastime = true
else
H = 0
end
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
if date.want_fix then
need_fix = true
else
return
end
end
end
date.want_fix = nil
if need_fix then
fix_numbers(numbers, y, m, d, H, M, S, date.partial, date.hastime, date.calendar)
return set_date_from_numbers(date, numbers, options)
end
date.year = y -- -9999 to 9999 ('n BC' → year = 1 - n)
date.month = m -- 1 to 12 (may be nil if partial)
date.day = d -- 1 to 31 (* = nil if partial)
date.hour = H -- 0 to 59 (*)
date.minute = M -- 0 to 59 (*)
date.second = S -- 0 to 59 (*)
if type(options) == 'table' then
for _, k in ipairs({ 'am', 'era', 'format' }) do
if options[k] then
date.options[k] = options[k]
end
end
end
return true
end
local function make_option_table(options1, options2)
-- If options1 is a string, return a table with its settings, or
-- if it is a table, use its settings.
-- Missing options are set from table options2 or defaults.
-- If a default is used, a flag is set so caller knows the value was not intentionally set.
-- Valid option settings are:
-- am: 'am', 'a.m.', 'AM', 'A.M.'
-- 'pm', 'p.m.', 'PM', 'P.M.' (each has same meaning as corresponding item above)
-- era: 'BCMINUS', 'BCNEGATIVE', 'BC', 'B.C.', 'BCE', 'B.C.E.', 'AD', 'A.D.', 'CE', 'C.E.'
-- Option am = 'am' does not mean the hour is AM; it means 'am' or 'pm' is used, depending on the hour,
-- and am = 'pm' has the same meaning.
-- Similarly, era = 'BC' means 'BC' is used if year <= 0.
-- BCMINUS displays a MINUS if year < 0 and the display format does not include %{era}.
-- BCNEGATIVE is similar but displays a hyphen.
local result = { bydefault = {} }
if type(options1) == 'table' then
result.am = options1.am
result.era = options1.era
elseif type(options1) == 'string' then
-- Example: 'am:AM era:BC' or 'am=AM era=BC'.
for item in options1:gmatch('%S+') do
local lhs, rhs = item:match('^(%w+)[:=](.+)$')
if lhs then
result[lhs] = rhs
end
end
end
options2 = type(options2) == 'table' and options2 or {}
local defaults = { am = 'am', era = 'BC' }
for k, v in pairs(defaults) do
if not result[k] then
if options2[k] then
result[k] = options2[k]
else
result[k] = v
result.bydefault[k] = true
end
end
end
return result
end
local ampm_options = {
-- lhs = input text accepted as an am/pm option
-- rhs = code used internally
['am'] = 'am',
['AM'] = 'AM',
['a.m.'] = 'a.m.',
['A.M.'] = 'A.M.',
['pm'] = 'am', -- same as am
['PM'] = 'AM',
['p.m.'] = 'a.m.',
['P.M.'] = 'A.M.',
}
local era_text = {
-- Text for displaying an era with a positive year (after adjusting
-- by replacing year with 1 - year if date.year <= 0).
-- options.era = { year<=0 , year>0 }
['BCMINUS'] = { 'BC' , '' , isbc = true, sign = MINUS },
['BCNEGATIVE'] = { 'BC' , '' , isbc = true, sign = '-' },
['BC'] = { 'BC' , '' , isbc = true },
['B.C.'] = { 'B.C.' , '' , isbc = true },
['BCE'] = { 'BCE' , '' , isbc = true },
['B.C.E.'] = { 'B.C.E.', '' , isbc = true },
['AD'] = { 'BC' , 'AD' },
['A.D.'] = { 'B.C.' , 'A.D.' },
['CE'] = { 'BCE' , 'CE' },
['C.E.'] = { 'B.C.E.', 'C.E.' },
}
local function get_era_for_year(era, year)
return (era_text[era] or era_text['BC'])[year > 0 and 2 or 1] or ''
end
local function strftime(date, format, options)
-- Return date formatted as a string using codes similar to those
-- in the C strftime library function.
local sformat = string.format
local shortcuts = {
['%c'] = '%-I:%M %p %-d %B %-Y %{era}', -- date and time: 2:30 pm 1 April 2016
['%x'] = '%-d %B %-Y %{era}', -- date: 1 April 2016
['%X'] = '%-I:%M %p', -- time: 2:30 pm
}
if shortcuts[format] then
format = shortcuts[format]
end
local codes = {
a = { field = 'dayabbr' },
A = { field = 'dayname' },
b = { field = 'monthabbr' },
B = { field = 'monthname' },
u = { fmt = '%d' , field = 'dowiso' },
w = { fmt = '%d' , field = 'dow' },
d = { fmt = '%02d', fmt2 = '%d', field = 'day' },
m = { fmt = '%02d', fmt2 = '%d', field = 'month' },
Y = { fmt = '%04d', fmt2 = '%d', field = 'year' },
H = { fmt = '%02d', fmt2 = '%d', field = 'hour' },
M = { fmt = '%02d', fmt2 = '%d', field = 'minute' },
S = { fmt = '%02d', fmt2 = '%d', field = 'second' },
j = { fmt = '%03d', fmt2 = '%d', field = 'dayofyear' },
I = { fmt = '%02d', fmt2 = '%d', field = 'hour', special = 'hour12' },
p = { field = 'hour', special = 'am' },
}
options = make_option_table(options, date.options)
local amopt = options.am
local eraopt = options.era
local function replace_code(spaces, modifier, id)
local code = codes[id]
if code then
local fmt = code.fmt
if modifier == '-' and code.fmt2 then
fmt = code.fmt2
end
local value = date[code.field]
if not value then
return nil -- an undefined field in a partial date
end
local special = code.special
if special then
if special == 'hour12' then
value = value % 12
value = value == 0 and 12 or value
elseif special == 'am' then
local ap = ({
['a.m.'] = { 'a.m.', 'p.m.' },
['AM'] = { 'AM', 'PM' },
['A.M.'] = { 'A.M.', 'P.M.' },
})[ampm_options[amopt]] or { 'am', 'pm' }
return (spaces == '' and '' or ' ') .. (value < 12 and ap[1] or ap[2])
end
end
if code.field == 'year' then
local sign = (era_text[eraopt] or {}).sign
if not sign or format:find('%{era}', 1, true) then
sign = ''
if value <= 0 then
value = 1 - value
end
else
if value >= 0 then
sign = ''
else
value = -value
end
end
return spaces .. sign .. sformat(fmt, value)
end
return spaces .. (fmt and sformat(fmt, value) or value)
end
end
local function replace_property(spaces, id)
if id == 'era' then
-- Special case so can use local era option.
local result = get_era_for_year(eraopt, date.year)
if result == '' then
return ''
end
return (spaces == '' and '' or ' ') .. result
end
local result = date[id]
if type(result) == 'string' then
return spaces .. result
end
if type(result) == 'number' then
return spaces .. tostring(result)
end
if type(result) == 'boolean' then
return spaces .. (result and '1' or '0')
end
-- This occurs if id is an undefined field in a partial date, or is the name of a function.
return nil
end
local PERCENT = '\127PERCENT\127'
return (format
:gsub('%%%%', PERCENT)
:gsub('(%s*)%%{(%w+)}', replace_property)
:gsub('(%s*)%%(%-?)(%a)', replace_code)
:gsub(PERCENT, '%%')
)
end
local function _date_text(date, fmt, options)
-- Return a formatted string representing the given date.
if not is_date(date) then
error('date:text: need a date (use "date:text()" with a colon)', 2)
end
if type(fmt) == 'string' and fmt:match('%S') then
if fmt:find('%', 1, true) then
return strftime(date, fmt, options)
end
elseif date.partial then
fmt = date.month and 'my' or 'y'
else
fmt = 'dmy'
if date.hastime then
fmt = (date.second > 0 and 'hms ' or 'hm ') .. fmt
end
end
local function bad_format()
-- For consistency with other format processing, return given format
-- (or cleaned format if original was not a string) if invalid.
return mw.text.nowiki(fmt)
end
if date.partial then
-- Ignore days in standard formats like 'ymd'.
if fmt == 'ym' or fmt == 'ymd' then
fmt = date.month and '%Y-%m %{era}' or '%Y %{era}'
elseif fmt == 'my' or fmt == 'dmy' or fmt == 'mdy' then
fmt = date.month and '%B %-Y %{era}' or '%-Y %{era}'
elseif fmt == 'y' then
fmt = date.month and '%-Y %{era}' or '%-Y %{era}'
else
return bad_format()
end
return strftime(date, fmt, options)
end
local function hm_fmt()
local plain = make_option_table(options, date.options).bydefault.am
return plain and '%H:%M' or '%-I:%M %p'
end
local need_time = date.hastime
local t = collection()
for item in fmt:gmatch('%S+') do
local f
if item == 'hm' then
f = hm_fmt()
need_time = false
elseif item == 'hms' then
f = '%H:%M:%S'
need_time = false
elseif item == 'ymd' then
f = '%Y-%m-%d %{era}'
elseif item == 'mdy' then
f = '%B %-d, %-Y %{era}'
elseif item == 'dmy' then
f = '%-d %B %-Y %{era}'
else
return bad_format()
end
t:add(f)
end
fmt = t:join(' ')
if need_time then
fmt = hm_fmt() .. ' ' .. fmt
end
return strftime(date, fmt, options)
end
local day_info = {
-- 0=Sun to 6=Sat
[0] = { 'Sun', 'Sunday' },
{ 'Mon', 'Monday' },
{ 'Tue', 'Tuesday' },
{ 'Wed', 'Wednesday' },
{ 'Thu', 'Thursday' },
{ 'Fri', 'Friday' },
{ 'Sat', 'Saturday' },
}
local month_info = {
-- 1=Jan to 12=Dec
{ 'Jan', 'January' },
{ 'Feb', 'February' },
{ 'Mar', 'March' },
{ 'Apr', 'April' },
{ 'May', 'May' },
{ 'Jun', 'June' },
{ 'Jul', 'July' },
{ 'Aug', 'August' },
{ 'Sep', 'September' },
{ 'Oct', 'October' },
{ 'Nov', 'November' },
{ 'Dec', 'December' },
}
local function name_to_number(text, translate)
if type(text) == 'string' then
return translate[text:lower()]
end
end
local function day_number(text)
return name_to_number(text, {
sun = 0, sunday = 0,
mon = 1, monday = 1,
tue = 2, tuesday = 2,
wed = 3, wednesday = 3,
thu = 4, thursday = 4,
fri = 5, friday = 5,
sat = 6, saturday = 6,
})
end
local function month_number(text)
return name_to_number(text, {
jan = 1, january = 1,
feb = 2, february = 2,
mar = 3, march = 3,
apr = 4, april = 4,
may = 5,
jun = 6, june = 6,
jul = 7, july = 7,
aug = 8, august = 8,
sep = 9, september = 9, sept = 9,
oct = 10, october = 10,
nov = 11, november = 11,
dec = 12, december = 12,
})
end
local function _list_text(list, fmt)
-- Return a list of formatted strings from a list of dates.
if not type(list) == 'table' then
error('date:list:text: need "list:text()" with a colon', 2)
end
local result = { join = _list_join }
for i, date in ipairs(list) do
result[i] = date:text(fmt)
end
return result
end
local function _date_list(date, spec)
-- Return a possibly empty numbered table of dates meeting the specification.
-- Dates in the list are in ascending order (oldest date first).
-- The spec should be a string of form "<count> <day> <op>"
-- where each item is optional and
-- count = number of items wanted in list
-- day = abbreviation or name such as Mon or Monday
-- op = >, >=, <, <= (default is > meaning after date)
-- If no count is given, the list is for the specified days in date's month.
-- The default day is date's day.
-- The spec can also be a positive or negative number:
-- -5 is equivalent to '5 <'
-- 5 is equivalent to '5' which is '5 >'
if not is_date(date) then
error('date:list: need a date (use "date:list()" with a colon)', 2)
end
local list = { text = _list_text }
if date.partial then
return list
end
local count, offset, operation
local ops = {
['>='] = { before = false, include = true },
['>'] = { before = false, include = false },
['<='] = { before = true , include = true },
['<'] = { before = true , include = false },
}
if spec then
if type(spec) == 'number' then
count = floor(spec + 0.5)
if count < 0 then
count = -count
operation = ops['<']
end
elseif type(spec) == 'string' then
local num, day, op = spec:match('^%s*(%d*)%s*(%a*)%s*([<>=]*)%s*$')
if not num then
return list
end
if num ~= '' then
count = tonumber(num)
end
if day ~= '' then
local dow = day_number(day:gsub('[sS]$', '')) -- accept plural days
if not dow then
return list
end
offset = dow - date.dow
end
operation = ops[op]
else
return list
end
end
offset = offset or 0
operation = operation or ops['>']
local datefrom, dayfirst, daylast
if operation.before then
if offset > 0 or (offset == 0 and not operation.include) then
offset = offset - 7
end
if count then
if count > 1 then
offset = offset - 7*(count - 1)
end
datefrom = date + offset
else
daylast = date.day + offset
dayfirst = daylast % 7
if dayfirst == 0 then
dayfirst = 7
end
end
else
if offset < 0 or (offset == 0 and not operation.include) then
offset = offset + 7
end
if count then
datefrom = date + offset
else
dayfirst = date.day + offset
daylast = date.monthdays
end
end
if not count then
if daylast < dayfirst then
return list
end
count = floor((daylast - dayfirst)/7) + 1
datefrom = Date(date, {day = dayfirst})
end
for i = 1, count do
if not datefrom then break end -- exceeds date limits
list[i] = datefrom
datefrom = datefrom + 7
end
return list
end
-- A table to get the current date/time (UTC), but only if needed.
local current = setmetatable({}, {
__index = function (self, key)
local d = os.date('!*t')
self.year = d.year
self.month = d.month
self.day = d.day
self.hour = d.hour
self.minute = d.min
self.second = d.sec
return rawget(self, key)
end })
local function extract_date(newdate, text)
-- Parse the date/time in text and return n, o where
-- n = table of numbers with date/time fields
-- o = table of options for AM/PM or AD/BC or format, if any
-- or return nothing if date is known to be invalid.
-- Caller determines if the values in n are valid.
-- A year must be positive ('1' to '9999'); use 'BC' for BC.
-- In a y-m-d string, the year must be four digits to avoid ambiguity
-- ('0001' to '9999'). The only way to enter year <= 0 is by specifying
-- the date as three numeric parameters like ymd Date(-1, 1, 1).
-- Dates of form d/m/y, m/d/y, y/m/d are rejected as potentially ambiguous.
local date, options = {}, {}
if text:sub(-1) == 'Z' then
-- Extract date/time from a Wikidata timestamp.
-- The year can be 1 to 16 digits but this module handles 1 to 4 digits only.
-- Examples: '+2016-06-21T14:30:00Z', '-0000000180-00-00T00:00:00Z'.
local sign, y, m, d, H, M, S = text:match('^([+%-])(%d+)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)Z$')
if sign then
y = tonumber(y)
if sign == '-' and y > 0 then
y = -y
end
if y <= 0 then
options.era = 'BCE'
end
date.year = y
m = tonumber(m)
d = tonumber(d)
H = tonumber(H)
M = tonumber(M)
S = tonumber(S)
if m == 0 then
newdate.partial = true
return date, options
end
date.month = m
if d == 0 then
newdate.partial = true
return date, options
end
date.day = d
if H > 0 or M > 0 or S > 0 then
date.hour = H
date.minute = M
date.second = S
end
return date, options
end
return
end
local function extract_ymd(item)
-- Called when no day or month has been set.
local y, m, d = item:match('^(%d%d%d%d)%-(%w+)%-(%d%d?)$')
if y then
if date.year then
return
end
if m:match('^%d%d?$') then
m = tonumber(m)
else
m = month_number(m)
end
if m then
date.year = tonumber(y)
date.month = m
date.day = tonumber(d)
return true
end
end
end
local function extract_day_or_year(item)
-- Called when a day would be valid, or
-- when a year would be valid if no year has been set and partial is set.
local number, suffix = item:match('^(%d%d?%d?%d?)(.*)$')
if number then
local n = tonumber(number)
if #number <= 2 and n <= 31 then
suffix = suffix:lower()
if suffix == '' or suffix == 'st' or suffix == 'nd' or suffix == 'rd' or suffix == 'th' then
date.day = n
return true
end
elseif suffix == '' and newdate.partial and not date.year then
date.year = n
return true
end
end
end
local function extract_month(item)
-- A month must be given as a name or abbreviation; a number could be ambiguous.
local m = month_number(item)
if m then
date.month = m
return true
end
end
local function extract_time(item)
local h, m, s = item:match('^(%d%d?):(%d%d)(:?%d*)$')
if date.hour or not h then
return
end
if s ~= '' then
s = s:match('^:(%d%d)$')
if not s then
return
end
end
date.hour = tonumber(h)
date.minute = tonumber(m)
date.second = tonumber(s) -- nil if empty string
return true
end
local item_count = 0
local index_time
local function set_ampm(item)
local H = date.hour
if H and not options.am and index_time + 1 == item_count then
options.am = ampm_options[item] -- caller checked this is not nil
if item:match('^[Aa]') then
if not (1 <= H and H <= 12) then
return
end
if H == 12 then
date.hour = 0
end
else
if not (1 <= H and H <= 23) then
return
end
if H <= 11 then
date.hour = H + 12
end
end
return true
end
end
for item in text:gsub(',', ' '):gsub(' ', ' '):gmatch('%S+') do
item_count = item_count + 1
if era_text[item] then
-- Era is accepted in peculiar places.
if options.era then
return
end
options.era = item
elseif ampm_options[item] then
if not set_ampm(item) then
return
end
elseif item:find(':', 1, true) then
if not extract_time(item) then
return
end
index_time = item_count
elseif date.day and date.month then
if date.year then
return -- should be nothing more so item is invalid
end
if not item:match('^(%d%d?%d?%d?)$') then
return
end
date.year = tonumber(item)
elseif date.day then
if not extract_month(item) then
return
end
elseif date.month then
if not extract_day_or_year(item) then
return
end
elseif extract_month(item) then
options.format = 'mdy'
elseif extract_ymd(item) then
options.format = 'ymd'
elseif extract_day_or_year(item) then
if date.day then
options.format = 'dmy'
end
else
return
end
end
if not date.year or date.year == 0 then
return
end
local era = era_text[options.era]
if era and era.isbc then
date.year = 1 - date.year
end
return date, options
end
local function autofill(date1, date2)
-- Fill any missing month or day in each date using the
-- corresponding component from the other date, if present,
-- or with 1 if both dates are missing the month or day.
-- This gives a good result for calculating the difference
-- between two partial dates when no range is wanted.
-- Return filled date1, date2 (two full dates).
local function filled(a, b)
local fillmonth, fillday
if not a.month then
fillmonth = b.month or 1
end
if not a.day then
fillday = b.day or 1
end
if fillmonth or fillday then -- need to create a new date
a = Date(a, { month = fillmonth, day = fillday })
end
return a
end
return filled(date1, date2), filled(date2, date1)
end
local function date_add_sub(lhs, rhs, is_sub)
-- Return a new date from calculating (lhs + rhs) or (lhs - rhs),
-- or return nothing if invalid.
-- The result is nil if the calculated date exceeds allowable limits.
-- Caller ensures that lhs is a date; its properties are copied for the new date.
if lhs.partial then
-- Adding to a partial is not supported.
-- Can subtract a date or partial from a partial, but this is not called for that.
return
end
local function is_prefix(text, word, minlen)
local n = #text
return (minlen or 1) <= n and n <= #word and text == word:sub(1, n)
end
local function do_days(n)
local forcetime, jd
if floor(n) == n then
jd = lhs.jd
else
forcetime = not lhs.hastime
jd = lhs.jdz
end
jd = jd + (is_sub and -n or n)
if forcetime then
jd = tostring(jd)
if not jd:find('.', 1, true) then
jd = jd .. '.0'
end
end
return Date(lhs, 'juliandate', jd)
end
if type(rhs) == 'number' then
-- Add/subtract days, including fractional days.
return do_days(rhs)
end
if type(rhs) == 'string' then
-- rhs is a single component like '26m' or '26 months' (with optional sign).
-- Fractions like '3.25d' are accepted for the units which are handled as days.
local sign, numstr, id = rhs:match('^%s*([+-]?)([%d%.]+)%s*(%a+)$')
if sign then
if sign == '-' then
is_sub = not (is_sub and true or false)
end
local y, m, days
local num = tonumber(numstr)
if not num then
return
end
id = id:lower()
if is_prefix(id, 'years') then
y = num
m = 0
elseif is_prefix(id, 'months') then
y = floor(num / 12)
m = num % 12
elseif is_prefix(id, 'weeks') then
days = num * 7
elseif is_prefix(id, 'days') then
days = num
elseif is_prefix(id, 'hours') then
days = num / 24
elseif is_prefix(id, 'minutes', 3) then
days = num / (24 * 60)
elseif is_prefix(id, 'seconds') then
days = num / (24 * 3600)
else
return
end
if days then
return do_days(days)
end
if numstr:find('.', 1, true) then
return
end
if is_sub then
y = -y
m = -m
end
assert(-11 <= m and m <= 11)
y = lhs.year + y
m = lhs.month + m
if m > 12 then
y = y + 1
m = m - 12
elseif m < 1 then
y = y - 1
m = m + 12
end
local d = math.min(lhs.day, days_in_month(y, m, lhs.calendar))
return Date(lhs, y, m, d)
end
end
if is_diff(rhs) then
local days = rhs.age_days
if (is_sub or false) ~= (rhs.isnegative or false) then
days = -days
end
return lhs + days
end
end
local full_date_only = {
dayabbr = true,
dayname = true,
dow = true,
dayofweek = true,
dowiso = true,
dayofweekiso = true,
dayofyear = true,
gsd = true,
juliandate = true,
jd = true,
jdz = true,
jdnoon = true,
}
-- Metatable for a date's calculated fields.
local datemt = {
__index = function (self, key)
if rawget(self, 'partial') then
if full_date_only[key] then return end
if key == 'monthabbr' or key == 'monthdays' or key == 'monthname' then
if not self.month then return end
end
end
local value
if key == 'dayabbr' then
value = day_info[self.dow][1]
elseif key == 'dayname' then
value = day_info[self.dow][2]
elseif key == 'dow' then
value = (self.jdnoon + 1) % 7 -- day-of-week 0=Sun to 6=Sat
elseif key == 'dayofweek' then
value = self.dow
elseif key == 'dowiso' then
value = (self.jdnoon % 7) + 1 -- ISO day-of-week 1=Mon to 7=Sun
elseif key == 'dayofweekiso' then
value = self.dowiso
elseif key == 'dayofyear' then
local first = Date(self.year, 1, 1, self.calendar).jdnoon
value = self.jdnoon - first + 1 -- day-of-year 1 to 366
elseif key == 'era' then
-- Era text (never a negative sign) from year and options.
value = get_era_for_year(self.options.era, self.year)
elseif key == 'format' then
value = self.options.format or 'dmy'
elseif key == 'gsd' then
-- GSD = 1 from 00:00:00 to 23:59:59 on 1 January 1 AD Gregorian calendar,
-- which is from jd 1721425.5 to 1721426.49999.
value = floor(self.jd - 1721424.5)
elseif key == 'juliandate' or key == 'jd' or key == 'jdz' then
local jd, jdz = julian_date(self)
rawset(self, 'juliandate', jd)
rawset(self, 'jd', jd)
rawset(self, 'jdz', jdz)
return key == 'jdz' and jdz or jd
elseif key == 'jdnoon' then
-- Julian date at noon (an integer) on the calendar day when jd occurs.
value = floor(self.jd + 0.5)
elseif key == 'isleapyear' then
value = is_leap_year(self.year, self.calendar)
elseif key == 'monthabbr' then
value = month_info[self.month][1]
elseif key == 'monthdays' then
value = days_in_month(self.year, self.month, self.calendar)
elseif key == 'monthname' then
value = month_info[self.month][2]
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
-- Date operators.
local function mt_date_add(lhs, rhs)
if not is_date(lhs) then
lhs, rhs = rhs, lhs -- put date on left (it must be a date for this to have been called)
end
return date_add_sub(lhs, rhs)
end
local function mt_date_sub(lhs, rhs)
if is_date(lhs) then
if is_date(rhs) then
return DateDiff(lhs, rhs)
end
return date_add_sub(lhs, rhs, true)
end
end
local function mt_date_concat(lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end
local function mt_date_tostring(self)
return self:text()
end
local function mt_date_eq(lhs, rhs)
-- Return true if dates identify same date/time where, for example,
-- Date(-4712, 1, 1, 'Julian') == Date(-4713, 11, 24, 'Gregorian') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
-- The months may both be nil, but must be the same.
return lhs.year == rhs.year and lhs.month == rhs.month and lhs.calendar == rhs.calendar
end
return lhs.jdz == rhs.jdz
end
local function mt_date_lt(lhs, rhs)
-- Return true if lhs < rhs, for example,
-- Date('1 Jan 2016') < Date('06:00 1 Jan 2016') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
if lhs.calendar ~= rhs.calendar then
return lhs.calendar == 'Julian'
end
if lhs.partial then
lhs = lhs.partial.first
end
if rhs.partial then
rhs = rhs.partial.first
end
end
return lhs.jdz < rhs.jdz
end
--[[ Examples of syntax to construct a date:
Date(y, m, d, 'julian') default calendar is 'gregorian'
Date(y, m, d, H, M, S, 'julian')
Date('juliandate', jd, 'julian') if jd contains "." text output includes H:M:S
Date('currentdate')
Date('currentdatetime')
Date('1 April 1995', 'julian') parse date from text
Date('1 April 1995 AD', 'julian') using an era sets a flag to do the same for output
Date('04:30:59 1 April 1995', 'julian')
Date(date) copy of an existing date
Date(date, t) same, updated with y,m,d,H,M,S fields from table t
Date(t) date with y,m,d,H,M,S fields from table t
]]
function Date(...) -- for forward declaration above
-- Return a table holding a date assuming a uniform calendar always applies
-- (proleptic Gregorian calendar or proleptic Julian calendar), or
-- return nothing if date is invalid.
-- A partial date has a valid year, however its month may be nil, and
-- its day and time fields are nil.
-- Field partial is set to false (if a full date) or a table (if a partial date).
local calendars = { julian = 'Julian', gregorian = 'Gregorian' }
local newdate = {
_id = uniq,
calendar = 'Gregorian', -- default is Gregorian calendar
hastime = false, -- true if input sets a time
hour = 0, -- always set hour/minute/second so don't have to handle nil
minute = 0,
second = 0,
options = {},
list = _date_list,
subtract = function (self, rhs, options)
return DateDiff(self, rhs, options)
end,
text = _date_text,
}
local argtype, datetext, is_copy, jd_number, tnums
local numindex = 0
local numfields = { 'year', 'month', 'day', 'hour', 'minute', 'second' }
local numbers = {}
for _, v in ipairs({...}) do
v = strip_to_nil(v)
local vlower = type(v) == 'string' and v:lower() or nil
if v == nil then
-- Ignore empty arguments after stripping so modules can directly pass template parameters.
elseif calendars[vlower] then
newdate.calendar = calendars[vlower]
elseif vlower == 'partial' then
newdate.partial = true
elseif vlower == 'fix' then
newdate.want_fix = true
elseif is_date(v) then
-- Copy existing date (items can be overridden by other arguments).
if is_copy or tnums then
return
end
is_copy = true
newdate.calendar = v.calendar
newdate.partial = v.partial
newdate.hastime = v.hastime
newdate.options = v.options
newdate.year = v.year
newdate.month = v.month
newdate.day = v.day
newdate.hour = v.hour
newdate.minute = v.minute
newdate.second = v.second
elseif type(v) == 'table' then
if tnums then
return
end
tnums = {}
local tfields = { year=1, month=1, day=1, hour=2, minute=2, second=2 }
for tk, tv in pairs(v) do
if tfields[tk] then
tnums[tk] = tonumber(tv)
end
if tfields[tk] == 2 then
newdate.hastime = true
end
end
else
local num = tonumber(v)
if not num and argtype == 'setdate' and numindex == 1 then
num = month_number(v)
end
if num then
if not argtype then
argtype = 'setdate'
end
if argtype == 'setdate' and numindex < 6 then
numindex = numindex + 1
numbers[numfields[numindex]] = num
elseif argtype == 'juliandate' and not jd_number then
jd_number = num
if type(v) == 'string' then
if v:find('.', 1, true) then
newdate.hastime = true
end
elseif num ~= floor(num) then
-- The given value was a number. The time will be used
-- if the fractional part is nonzero.
newdate.hastime = true
end
else
return
end
elseif argtype then
return
elseif type(v) == 'string' then
if v == 'currentdate' or v == 'currentdatetime' or v == 'juliandate' then
argtype = v
else
argtype = 'datetext'
datetext = v
end
else
return
end
end
end
if argtype == 'datetext' then
if tnums or not set_date_from_numbers(newdate, extract_date(newdate, datetext)) then
return
end
elseif argtype == 'juliandate' then
newdate.partial = nil
newdate.jd = jd_number
if not set_date_from_jd(newdate) then
return
end
elseif argtype == 'currentdate' or argtype == 'currentdatetime' then
newdate.partial = nil
newdate.year = current.year
newdate.month = current.month
newdate.day = current.day
if argtype == 'currentdatetime' then
newdate.hour = current.hour
newdate.minute = current.minute
newdate.second = current.second
newdate.hastime = true
end
newdate.calendar = 'Gregorian' -- ignore any given calendar name
elseif argtype == 'setdate' then
if tnums or not set_date_from_numbers(newdate, numbers) then
return
end
elseif not (is_copy or tnums) then
return
end
if tnums then
newdate.jd = nil -- force recalculation in case jd was set before changes from tnums
if not set_date_from_numbers(newdate, tnums) then
return
end
end
if newdate.partial then
local year = newdate.year
local month = newdate.month
local first = Date(year, month or 1, 1, newdate.calendar)
month = month or 12
local last = Date(year, month, days_in_month(year, month), newdate.calendar)
newdate.partial = { first = first, last = last }
else
newdate.partial = false -- avoid index lookup
end
setmetatable(newdate, datemt)
local readonly = {}
local mt = {
__index = newdate,
__newindex = function(t, k, v) error('date.' .. tostring(k) .. ' is read-only', 2) end,
__add = mt_date_add,
__sub = mt_date_sub,
__concat = mt_date_concat,
__tostring = mt_date_tostring,
__eq = mt_date_eq,
__lt = mt_date_lt,
}
return setmetatable(readonly, mt)
end
local function _diff_age(diff, code, options)
-- Return a tuple of integer values from diff as specified by code, except that
-- each integer may be a list of two integers for a diff with a partial date, or
-- return nil if the code is not supported.
-- If want round, the least significant unit is rounded to nearest whole unit.
-- For a duration, an extra day is added.
local wantround, wantduration, wantrange
if type(options) == 'table' then
wantround = options.round
wantduration = options.duration
wantrange = options.range
else
wantround = options
end
if not is_diff(diff) then
local f = wantduration and 'duration' or 'age'
error(f .. ': need a date difference (use "diff:' .. f .. '()" with a colon)', 2)
end
if diff.partial then
-- Ignore wantround, wantduration.
local function choose(v)
if type(v) == 'table' then
if not wantrange or v[1] == v[2] then
-- Example: Date('partial', 2005) - Date('partial', 2001) gives
-- diff.years = { 3, 4 } to show the range of possible results.
-- If do not want a range, choose the second value as more expected.
return v[2]
end
end
return v
end
if code == 'ym' or code == 'ymd' then
if not wantrange and diff.iszero then
-- This avoids an unexpected result such as
-- Date('partial', 2001) - Date('partial', 2001)
-- giving diff = { years = 0, months = { 0, 11 } }
-- which would be reported as 0 years and 11 months.
return 0, 0
end
return choose(diff.partial.years), choose(diff.partial.months)
end
if code == 'y' then
return choose(diff.partial.years)
end
if code == 'm' or code == 'w' or code == 'd' then
return choose({ diff.partial.mindiff:age(code), diff.partial.maxdiff:age(code) })
end
return nil
end
local extra_days = wantduration and 1 or 0
if code == 'wd' or code == 'w' or code == 'd' then
local offset = wantround and 0.5 or 0
local days = diff.age_days + extra_days
if code == 'wd' or code == 'd' then
days = floor(days + offset)
if code == 'd' then
return days
end
return floor(days/7), days % 7
end
return floor(days/7 + offset)
end
local H, M, S = diff.hours, diff.minutes, diff.seconds
if code == 'dh' or code == 'dhm' or code == 'dhms' or code == 'h' or code == 'hm' or code == 'hms' then
local days = floor(diff.age_days + extra_days)
local inc_hour
if wantround then
if code == 'dh' or code == 'h' then
if M >= 30 then
inc_hour = true
end
elseif code == 'dhm' or code == 'hm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
else
-- Nothing needed because S is an integer.
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
days = days + 1
end
end
end
if code == 'dh' or code == 'dhm' or code == 'dhms' then
if code == 'dh' then
return days, H
elseif code == 'dhm' then
return days, H, M
else
return days, H, M, S
end
end
local hours = days * 24 + H
if code == 'h' then
return hours
elseif code == 'hm' then
return hours, M
end
return hours, M, S
end
if wantround then
local inc_hour
if code == 'ymdh' or code == 'ymwdh' then
if M >= 30 then
inc_hour = true
end
elseif code == 'ymdhm' or code == 'ymwdhm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
elseif code == 'ymd' or code == 'ymwd' or code == 'yd' or code == 'md' then
if H >= 12 then
extra_days = extra_days + 1
end
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
extra_days = extra_days + 1
end
end
end
local y, m, d = diff.years, diff.months, diff.days
if extra_days > 0 then
d = d + extra_days
if d > 28 or code == 'yd' then
-- Recalculate in case have passed a month.
diff = diff.date1 + extra_days - diff.date2
y, m, d = diff.years, diff.months, diff.days
end
end
if code == 'ymd' then
return y, m, d
elseif code == 'yd' then
if y > 0 then
-- It is known that diff.date1 > diff.date2.
diff = diff.date1 - (diff.date2 + (y .. 'y'))
end
return y, floor(diff.age_days)
elseif code == 'md' then
return y * 12 + m, d
elseif code == 'ym' or code == 'm' then
if wantround then
if d >= 16 then
m = m + 1
if m >= 12 then
m = 0
y = y + 1
end
end
end
if code == 'ym' then
return y, m
end
return y * 12 + m
elseif code == 'ymw' then
local weeks = floor(d/7)
if wantround then
local days = d % 7
if days > 3 or (days == 3 and H >= 12) then
weeks = weeks + 1
end
end
return y, m, weeks
elseif code == 'ymwd' then
return y, m, floor(d/7), d % 7
elseif code == 'ymdh' then
return y, m, d, H
elseif code == 'ymwdh' then
return y, m, floor(d/7), d % 7, H
elseif code == 'ymdhm' then
return y, m, d, H, M
elseif code == 'ymwdhm' then
return y, m, floor(d/7), d % 7, H, M
end
if code == 'y' then
if wantround and m >= 6 then
y = y + 1
end
return y
end
return nil
end
local function _diff_duration(diff, code, options)
if type(options) ~= 'table' then
options = { round = options }
end
options.duration = true
return _diff_age(diff, code, options)
end
-- Metatable for some operations on date differences.
diffmt = { -- for forward declaration above
__concat = function (lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end,
__tostring = function (self)
return tostring(self.age_days)
end,
__index = function (self, key)
local value
if key == 'age_days' then
if rawget(self, 'partial') then
local function jdz(date)
return (date.partial and date.partial.first or date).jdz
end
value = jdz(self.date1) - jdz(self.date2)
else
value = self.date1.jdz - self.date2.jdz
end
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
function DateDiff(date1, date2, options) -- for forward declaration above
-- Return a table with the difference between two dates (date1 - date2).
-- The difference is negative if date1 is older than date2.
-- Return nothing if invalid.
-- If d = date1 - date2 then
-- date1 = date2 + d
-- If date1 >= date2 and the dates have no H:M:S time specified then
-- date1 = date2 + (d.years..'y') + (d.months..'m') + d.days
-- where the larger time units are added first.
-- The result of Date(2015,1,x) + '1m' is Date(2015,2,28) for
-- x = 28, 29, 30, 31. That means, for example,
-- d = Date(2015,3,3) - Date(2015,1,31)
-- gives d.years, d.months, d.days = 0, 1, 3 (excluding date1).
if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then
return
end
local wantfill
if type(options) == 'table' then
wantfill = options.fill
end
local isnegative = false
local iszero = false
if date1 < date2 then
isnegative = true
date1, date2 = date2, date1
elseif date1 == date2 then
iszero = true
end
-- It is known that date1 >= date2 (period is from date2 to date1).
if date1.partial or date2.partial then
-- Two partial dates might have timelines:
---------------------A=================B--- date1 is from A to B inclusive
--------C=======D-------------------------- date2 is from C to D inclusive
-- date1 > date2 iff A > C (date1.partial.first > date2.partial.first)
-- The periods can overlap ('April 2001' - '2001'):
-------------A===B------------------------- A=2001-04-01 B=2001-04-30
--------C=====================D------------ C=2001-01-01 D=2001-12-31
if wantfill then
date1, date2 = autofill(date1, date2)
else
local function zdiff(date1, date2)
local diff = date1 - date2
if diff.isnegative then
return date1 - date1 -- a valid diff in case we call its methods
end
return diff
end
local function getdate(date, which)
return date.partial and date.partial[which] or date
end
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
local years, months
if maxdiff.years == mindiff.years then
years = maxdiff.years
if maxdiff.months == mindiff.months then
months = maxdiff.months
else
months = { mindiff.months, maxdiff.months }
end
else
years = { mindiff.years, maxdiff.years }
end
return setmetatable({
date1 = date1,
date2 = date2,
partial = {
years = years,
months = months,
maxdiff = maxdiff,
mindiff = mindiff,
},
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
end
local y1, m1 = date1.year, date1.month
local y2, m2 = date2.year, date2.month
local years = y1 - y2
local months = m1 - m2
local d1 = date1.day + hms(date1)
local d2 = date2.day + hms(date2)
local days, time
if d1 >= d2 then
days = d1 - d2
else
months = months - 1
-- Get days in previous month (before the "to" date) given December has 31 days.
local dpm = m1 > 1 and days_in_month(y1, m1 - 1, date1.calendar) or 31
if d2 >= dpm then
days = d1 - hms(date2)
else
days = dpm - d2 + d1
end
end
if months < 0 then
years = years - 1
months = months + 12
end
days, time = math.modf(days)
local H, M, S = h_m_s(time)
return setmetatable({
date1 = date1,
date2 = date2,
partial = false, -- avoid index lookup
years = years,
months = months,
days = days,
hours = H,
minutes = M,
seconds = S,
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
return {
_current = current,
_Date = Date,
_days_in_month = days_in_month,
}
ba95c5be544bbca7b661a5038c292cb5ef61de6d
Module:Protection banner/config
828
111
216
2021-12-07T06:46:39Z
zhwp>Xiplus
0
extendedconfirmed
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[那艺娜维基:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[那艺娜维基:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[那艺娜维基:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[那艺娜维基:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[那艺娜维基:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[那艺娜维基:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[那艺娜维基:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[那艺娜维基:封禁方针|封禁]]或被'
.. '[[那艺娜维基:編輯禁制方針|編輯禁制]]用户的[[那艺娜维基:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[那艺娜维基:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[那艺娜维基:高風險模板|高風險模板]],'
.. '已被永久[[那艺娜维基:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]或'
.. '[[那艺娜维基:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏|破坏]]而被保护的页面',
text = '由于[[那艺娜维基:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[那艺娜维基:用户权限'
.. '级别#新用户|新用户]]或[[那艺娜维基:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[那艺娜维基:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[那艺娜维基:用户权限级别#新用户|新用户]] or'
.. ' [[那艺娜维基:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[那艺娜维基:Reviewing|reviewers]] or'
.. ' [[那艺娜维基:管理员|管理员]] are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[那艺娜维基:共识'
.. '|共识]]基础,您可以向'
.. '[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[那艺娜维基:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[那艺娜维基:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[那艺娜维基:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[那艺娜维基:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = '那艺娜维基:保護方針#全保护',
templateeditor = '那艺娜维基:保護方針#模板保护',
extendedconfirmed = '那艺娜维基:保護方針#延伸確認保護',
autoconfirmed = '那艺娜维基:保護方針#半保护'
},
move = {
default = '那艺娜维基:保護方針#移动保护'
},
autoreview = {
autoconfirmed = '那艺娜维基:保護方針#pc1',
reviewer = '那艺娜维基:保護方針#pc2'
},
upload = {
default = '那艺娜维基:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[那艺娜维基:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
7094c99bbb3daa4ca9c6e7979c5de465b77c2398
274
216
2021-12-07T06:46:39Z
zhwp>Xiplus
0
extendedconfirmed
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[那艺娜维基:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[那艺娜维基:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[那艺娜维基:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[那艺娜维基:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[那艺娜维基:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[那艺娜维基:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[那艺娜维基:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[那艺娜维基:封禁方针|封禁]]或被'
.. '[[那艺娜维基:編輯禁制方針|編輯禁制]]用户的[[那艺娜维基:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[那艺娜维基:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[那艺娜维基:高風險模板|高風險模板]],'
.. '已被永久[[那艺娜维基:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]或'
.. '[[那艺娜维基:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏|破坏]]而被保护的页面',
text = '由于[[那艺娜维基:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[那艺娜维基:用户权限'
.. '级别#新用户|新用户]]或[[那艺娜维基:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[那艺娜维基:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[那艺娜维基:用户权限级别#新用户|新用户]] or'
.. ' [[那艺娜维基:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[那艺娜维基:Reviewing|reviewers]] or'
.. ' [[那艺娜维基:管理员|管理员]] are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[那艺娜维基:共识'
.. '|共识]]基础,您可以向'
.. '[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[那艺娜维基:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[那艺娜维基:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[那艺娜维基:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[那艺娜维基:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = '那艺娜维基:保護方針#全保护',
templateeditor = '那艺娜维基:保護方針#模板保护',
extendedconfirmed = '那艺娜维基:保護方針#延伸確認保護',
autoconfirmed = '那艺娜维基:保護方針#半保护'
},
move = {
default = '那艺娜维基:保護方針#移动保护'
},
autoreview = {
autoconfirmed = '那艺娜维基:保護方針#pc1',
reviewer = '那艺娜维基:保護方針#pc2'
},
upload = {
default = '那艺娜维基:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[那艺娜维基:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
7094c99bbb3daa4ca9c6e7979c5de465b77c2398
394
274
2021-12-07T06:46:39Z
zhwp>Xiplus
0
extendedconfirmed
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[Wikipedia:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[Wikipedia:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[Wikipedia:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[Wikipedia:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[Wikipedia:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[Wikipedia:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[Wikipedia:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[Wikipedia:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[Wikipedia:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[Wikipedia:封禁方针|封禁]]或被'
.. '[[Wikipedia:編輯禁制方針|編輯禁制]]用户的[[Wikipedia:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[Wikipedia:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[Wikipedia:高風險模板|高風險模板]],'
.. '已被永久[[Wikipedia:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[Wikipedia:共识|共识]]基础,您可以'
.. '向[[Wikipedia:管理员|管理员]]或'
.. '[[Wikipedia:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[Wikipedia:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[Wikipedia:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[Wikipedia:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[Wikipedia:破坏|破坏]]而被保护的页面',
text = '由于[[Wikipedia:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[Wikipedia:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[Wikipedia:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[Wikipedia:用户权限'
.. '级别#新用户|新用户]]或[[Wikipedia:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[Wikipedia:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[Wikipedia:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[Wikipedia:用户权限级别#新用户|新用户]] or'
.. ' [[Wikipedia:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[Wikipedia:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[Wikipedia:Reviewing|reviewers]] or'
.. ' [[Wikipedia:管理员|管理员]] are currently'
.. ' [[Wikipedia:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[Wikipedia:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[Wikipedia:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[Wikipedia:共识'
.. '|共识]]基础,您可以向'
.. '[[Wikipedia:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[Wikipedia:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[Wikipedia:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[Wikipedia:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[Wikipedia:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[Wikipedia:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[Wikipedia:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[Wikipedia:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[Wikipedia:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[Wikipedia:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[Wikipedia:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[Wikipedia:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[Wikipedia:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = 'Wikipedia:保護方針#全保护',
templateeditor = 'Wikipedia:保護方針#模板保护',
extendedconfirmed = 'Wikipedia:保護方針#延伸確認保護',
autoconfirmed = 'Wikipedia:保護方針#半保护'
},
move = {
default = 'Wikipedia:保護方針#移动保护'
},
autoreview = {
autoconfirmed = 'Wikipedia:保護方針#pc1',
reviewer = 'Wikipedia:保護方針#pc2'
},
upload = {
default = 'Wikipedia:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[Wikipedia:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[Wikipedia:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[Wikipedia:共识|共识]]基础,您可以'
.. '向[[Wikipedia:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
a2d02e109a2cdc5492b7f2f6ca1fc5789021ded6
Template:Yesno
10
212
442
2022-02-11T03:59:58Z
zhwp>Xiplus
0
自[[Template:Yesno/sandbox]]合并[[Special:Contributions/Xiplus|Xiplus]]的[[Special:PermaLink/69836169|版本69836169]]
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#switch: {{<includeonly>safesubst:</includeonly>lc: {{{1|¬}}} }}
|no
|n
|false
|f
|否
|0 = {{{no|<!-- null -->}}}
| = {{{blank|{{{no|<!-- null -->}}}}}}
|¬ = {{{¬|}}}
|yes
|y
|true
|t
|是
|1 = {{{yes|yes}}}
|#default = {{{def|{{{yes|yes}}}}}}
}}<noinclude>
{{documentation}}
</noinclude>
a0ba60b6ae5ad344f4e4a2ea033770d6131cf7c6
Template:Tag
10
189
390
2022-04-04T15:22:29Z
zhwp>SunAfterRain
0
=
wikitext
text/x-wiki
<code style="white-space:nowrap;">{{#switch:{{{2|pair}}}
|c|close = <!--nothing-->
|s|single
|o|open
|p|pair = <{{{1|tag}}}{{#if:{{{參數|{{{参数|{{{params|{{{attribs|{{{4|}}}}}}}}}}}}}}}| {{{參數|{{{参数|{{{params|{{{attribs|{{{4|}}}}}}}}}}}}}}}}}
}}{{#switch:{{{2|pair}}}
|c|close|关|關|右 = {{{內容|{{{内容|{{{文字|{{{content|{{{3|}}}}}}}}}}}}}}}
|s|single =  />
|o|open|开|開|左 = >{{{內容|{{{内容|{{{文字|{{{content|{{{3|}}}}}}}}}}}}}}}
|p|pair = >{{{內容|{{{内容|{{{文字|{{{content|{{{3|...}}}}}}}}}}}}}}}
}}{{#switch:{{{2|pair}}}
|s|single
|o|open|开|開|左 = <!--nothing-->
|c|close|关|關|右
|p|pair = </{{{1|tag}}}>
}}</code><noinclude>
{{documentation}}
</noinclude>
f159dd876de61be362b572be895a22804a8b1017
Endflatlist
0
294
611
2022-04-24T00:05:42Z
zhwp>Xiplus-abot
0
已更改“[[Template:Endflatlist]]”的保护设置:高風險模板:5002引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
</div><noinclude>
{{documentation|Template:Flatlist/doc}}
</noinclude>
8664fe211feb15b6d1b29c9f1b83dccc0cabbb5a
Template:Endflatlist
10
301
625
2022-04-24T00:05:42Z
zhwp>Xiplus-abot
0
已更改“[[Template:Endflatlist]]”的保护设置:高風險模板:5002引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员和管理员](无限期)[移动=仅允许模板编辑员和管理员](无限期))
wikitext
text/x-wiki
</div><noinclude>
{{documentation|Template:Flatlist/doc}}
</noinclude>
8664fe211feb15b6d1b29c9f1b83dccc0cabbb5a
Module:Citation/CS1/Whitelist
828
177
360
2022-04-26T16:25:36Z
zhwp>Antigng
0
[[WP:PP|ep]]: [[Special:Diff/71338344|71338344]]
Scribunto
text/plain
--[[--------------------------< P A R A M E T E R S N O T S U P P O R T E D >------------------------------
This is a list of parameters that once were but now are no longer supported:
['albumlink'] = nil, -- unique alias of titlelink used by old cite AV media notes
['albumtype'] = nil, -- controled inappropriate functionality in the old cite AV media notes
['artist'] = nil, -- unique alias of others used by old cite AV media notes
['Author'] = nil, -- non-standard capitalization
['authorformat'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['author-format'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['author-name-separator'] = nil,-- primarily used to support Vancouver format which functionality now part of name-list-format
['author-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['began'] = nil, -- module handles date ranges; cite episode and cite series
['chapterlink'] = nil, -- if ever necessary to link to a chapter article, |chapter= can be wikilinked
['chapter-link'] = nil, --
['cointerviewers'] = nil, -- unique alias of others used by old cite interview
['day'] = nil, -- deprecated in {{citation/core}} and somehow undeprecated in Module:Citation/CS1 and now finally removed
['director'] = nil, -- unique alias of author used by old cite DVD-notes
['DoiBroken'] = nil, -- not used, non-standard captialization
['Editor'] = nil, -- non-standard capitalization
['editorformat'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['EditorSurname'] = nil, -- non-standard capitalization
['editor-format'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['EditorGiven'] = nil, -- non-standard capitalization
['editor-name-separator'] = nil,-- primarily used to support Vancouver format which functionality now part of name-list-format
['editor-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['Embargo'] = nil, -- not used, non-standard capitalization
['ended'] = nil, -- module handles date ranges; cite episode and cite series
['month'] = nil, -- functionality supported by |date=
['name-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['notestitle'] = nil, -- unique alias of chapter used by old cite AV media notes
['PPrefix'] = nil, -- non-standard capitalization
['PPPrefix'] = nil, -- not used, non-standard capitalization
['pp-prefix'] = nil, -- not used, not documented
['p-prefix'] = nil, -- not used, not documented
['publisherid'] = nil, -- unique alias of id used by old cite AV media notes and old cite DVD-notes
['Ref'] = nil, -- non-statndard capitalization
['separator'] = nil, -- this functionality now provided by |mode=
['titleyear'] = nil, -- unique alias of origyear used by old cite DVD-notes
['Author#'] = nil, -- non-standard capitalization
['authors#'] = nil, -- no need for multiple lists of author names
['Editor#'] = nil, -- non-standard capitalization
['editors#'] = nil, -- no need for multiple lists of editor names
['EditorGiven#'] = nil, -- non-standard capitalization
['EditorSurname#'] = nil, -- non-standard capitalization
]]
--[[--------------------------< S U P P O R T E D P A R A M E T E R S >--------------------------------------
Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values:
true - these parameters are valid and supported parameters
false - these parameters are deprecated but still supported
nil - these parameters are no longer supported (when setting a parameter to nil, leave a comment stating the reasons for invalidating the parameter)
]]
local whitelist = {}
local basic_arguments = {
['accessdate'] = true,
['access-date'] = true,
['agency'] = true,
['airdate'] = true,
['air-date'] = true,
['archivedate'] = true,
['archive-date'] = true,
['archive-format'] = true,
['archiveurl'] = true,
['archive-url'] = true,
['article'] = true,
['arxiv'] = true,
['ARXIV'] = true,
['asin'] = true,
['ASIN'] = true,
['asin-tld'] = true,
['ASIN-TLD'] = true,
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-last'] = true,
['authorlink'] = true,
['author-link'] = true,
['authormask'] = true,
['author-mask'] = true,
['authors'] = true,
['bibcode'] = true,
['BIBCODE'] = true,
['bibcode-access'] = true,
['biorxiv'] = true,
['booktitle'] = true,
['book-title'] = true,
['callsign'] = true, -- cite interview
['call-sign'] = true, -- cite interview
['cartography'] = true,
['chapter'] = true,
['chapter-format'] = true,
['chapterurl'] = true,
['chapter-url'] = true,
['chapter-url-access'] = true,
['citeseerx'] = true,
['city'] = true, -- cite interview, cite episode, cite serial
['class'] = true, -- cite arxiv and arxiv identifiers
['cn'] = true,
['CN'] = true,
['coauthor'] = false, -- deprecated
['coauthors'] = false, -- deprecated
['conference'] = true,
['conference-format'] = true,
['conferenceurl'] = true,
['conference-url'] = true,
['contribution'] = true,
['contribution-format'] = true,
['contributionurl'] = true,
['contribution-url'] = true,
['contributor'] = true,
['contributor-first'] = true,
['contributor-last'] = true,
['contributor-link'] = true,
['contributor-mask'] = true,
['credits'] = true, -- cite episode, cite serial
['date'] = true,
['deadurl'] = true,
['dead-url'] = true,
['degree'] = true,
['department'] = true,
['dictionary'] = true,
['displayauthors'] = true,
['display-authors'] = true,
['displayeditors'] = true,
['display-editors'] = true,
['docket'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken'] = true,
['doi_brokendate'] = true,
['doi-broken-date'] = true,
['doi_inactivedate'] = true,
['doi-inactive-date'] = true,
['edition'] = true,
['editor'] = true,
['editor-first'] = true,
['editor-given'] = true,
['editor-last'] = true,
['editorlink'] = true,
['editor-link'] = true,
['editormask'] = true,
['editor-mask'] = true,
['editors'] = true,
['editor-surname'] = true,
['eissn'] = true,
['EISSN'] = true,
['embargo'] = true,
['encyclopaedia'] = true,
['encyclopedia'] = true,
['entry'] = true,
['episode'] = true, -- cite serial only TODO: make available to cite episode?
['episodelink'] = true, -- cite episode and cite serial
['episode-link'] = true, -- cite episode and cite serial
['eprint'] = true, -- cite arxiv and arxiv identifiers
['event'] = true,
['event-format'] = true,
['eventurl'] = true,
['event-url'] = true,
['first'] = true,
['format'] = true,
['given'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['host'] = true,
['id'] = true,
['ID'] = true,
['ignoreisbnerror'] = true,
['ignore-isbn-error'] = true,
['in'] = true,
['inset'] = true,
['institution'] = true,
['interviewer'] = true, --cite interview
['interviewers'] = true, --cite interview
['isbn'] = true,
['ISBN'] = true,
['isbn13'] = true,
['ISBN13'] = true,
['ismn'] = true,
['ISMN'] = true,
['issn'] = true,
['ISSN'] = true,
['issue'] = true,
['jfm'] = true,
['JFM'] = true,
['journal'] = true,
['jstor'] = true,
['JSTOR'] = true,
['jstor-access'] = true,
['language'] = true,
['last'] = true,
['lastauthoramp'] = true,
['last-author-amp'] = true,
['laydate'] = true,
['lay-date'] = true,
['laysource'] = true,
['lay-source'] = true,
['laysummary'] = true,
['lay-summary'] = true,
['lay-format'] = true,
['layurl'] = true,
['lay-url'] = true,
['lccn'] = true,
['LCCN'] = true,
['location'] = true,
['magazine'] = true,
['mailinglist'] = true, -- cite mailing list only
['mailing-list'] = true, -- cite mailing list only
['map'] = true, -- cite map only
['map-format'] = true, -- cite map only
['mapurl'] = true, -- cite map only
['map-url'] = true, -- cite map only
['map-url-access'] = true, -- cite map only
['medium'] = true,
['message-id'] = true, -- cite newsgroup
['minutes'] = true,
['mode'] = true,
['mr'] = true,
['MR'] = true,
['name-list-format'] = true,
['name-list-style'] = true,
['network'] = true,
['newsgroup'] = true,
['newspaper'] = true,
['nocat'] = true,
['no-cat'] = true,
['nopp'] = true,
['no-pp'] = true,
['notracking'] = true,
['no-tracking'] = true,
['number'] = true,
['oclc'] = true,
['OCLC'] = true,
['ol'] = true,
['OL'] = true,
['ol-access'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['others'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['people'] = true,
['periodical'] = true,
['place'] = true,
['pmc'] = true,
['PMC'] = true,
['pmid'] = true,
['PMID'] = true,
['postscript'] = true,
['pp'] = true,
['program'] = true, -- cite interview
['publicationdate'] = true,
['publication-date'] = true,
['publicationplace'] = true,
['publication-place'] = true,
['publisher'] = true,
['quotation'] = true,
['quote'] = true,
['ref'] = true,
['registration'] = true,
['rfc'] = true,
['RFC'] = true,
['s2cid'] = true,
['s2cid-access'] = true,
['scale'] = true,
['script-chapter'] = true,
['script-title'] = true,
['season'] = true,
['section'] = true,
['section-format'] = true,
['sections'] = true, -- cite map only
['sectionurl'] = true,
['section-url'] = true,
['section-url-access'] = true,
['series'] = true,
['serieslink'] = true,
['series-link'] = true,
['seriesno'] = true,
['series-no'] = true,
['seriesnumber'] = true,
['series-number'] = true,
['series-separator'] = true,
['sheet'] = true, -- cite map only
['sheets'] = true, -- cite map only
['ssrn'] = true,
['SSRN'] = true,
['station'] = true,
['subject'] = true,
['subjectlink'] = true,
['subject-link'] = true,
['subscription'] = true,
['surname'] = true,
['template doc demo'] = true,
['template-doc-demo'] = true,
['time'] = true,
['timecaption'] = true,
['time-caption'] = true,
['title'] = true,
['titlelink'] = true,
['title-link'] = true,
['title_zh'] = true,
['trans_chapter'] = true,
['trans-chapter'] = true,
['trans-map'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcripturl'] = true,
['transcript-url'] = true,
['trans_title'] = true,
['trans-title'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-last'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['type'] = true,
['url'] = true,
['URL'] = true,
['urlaccess'] = true,
['url-access'] = true,
['urlstatus'] = true,
['url-status'] = true,
['vauthors'] = true,
['veditors'] = true,
['version'] = true,
['via'] = true,
['volume'] = true,
['website'] = true,
['work'] = true,
['year'] = true,
['zbl'] = true,
['ZBL'] = true,
['unified'] = true,
['csbn'] = true,
['CSBN'] = true,
}
local numbered_arguments = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-link#'] = true,
['author#link'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author-mask#'] = true,
['author#mask'] = true,
['author#-mask'] = true,
['authormask#'] = true,
['contributor#'] = true,
['contributor-first#'] = true,
['contributor#-first'] = true,
['contributor-last#'] = true,
['contributor#-last'] = true,
['contributor-link#'] = true,
['contributor#-link'] = true,
['contributor-mask#'] = true,
['contributor#-mask'] = true,
['editor#'] = true,
['editor-first#'] = true,
['editor#-first'] = true,
['editor#-given'] = true,
['editor-given#'] = true,
['editor-last#'] = true,
['editor#-last'] = true,
['editor-link#'] = true,
['editor#link'] = true,
['editor#-link'] = true,
['editorlink#'] = true,
['editor-mask#'] = true,
['editor#mask'] = true,
['editor#-mask'] = true,
['editormask#'] = true,
['editor#-surname'] = true,
['editor-surname#'] = true,
['first#'] = true,
['given#'] = true,
['last#'] = true,
['subject#'] = true,
['subject-link#'] = true,
['subject#link'] = true,
['subject#-link'] = true,
['subjectlink#'] = true,
['surname#'] = true,
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
return {basic_arguments = basic_arguments, numbered_arguments = numbered_arguments};
17890b7a4dad9667afd0644db8db6c1310f214b0
Module:Citation/CS1/Utilities
828
180
366
2022-04-26T16:29:49Z
zhwp>Antigng
0
[[WP:PP|ep]]: [[Special:Diff/71332844|71332844]]
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------
Converts a hyphen to a dash
]]
--
local function hyphen_to_dash( str )
if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then
return str;
end
return str:gsub( '-', '–' );
end
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
This function is global because it is called from both this module and from Date validation
]]
function is_set( var )
return not (var == nil or var == '');
end
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------
Locates and returns the first set value in a table of values where the order established in the table,
left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set.
This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs
version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate
the for-loop before it reached the actual end of the list.
]]
local function first_set (list, count)
local i = 1;
while i <= count do -- loop through all items in list
if is_set( list[i] ) then
return list[i]; -- return the first set list member
end
i = i + 1; -- point to next
end
end
--[[--------------------------< I N _ A R R A Y >--------------------------------------------------------------
Whether needle is in haystack
]]
local function in_array( needle, haystack )
if needle == nil then
return false;
end
for n,v in ipairs( haystack ) do
if v == needle then
return n;
end
end
return false;
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Populates numbered arguments in a message string using an argument table.
]]
local function substitute( msg, args )
return args and mw.message.newRawMessage( msg, args ):plain() or msg;
end
--[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------
When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else
with allow_empty = false, <str> must have at least one character inside the markup
with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context.
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.
]]
local function has_accept_as_written (str, allow_empty)
local count;
if true == allow_empty then
str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set
else
str, count = str:gsub ('^%(%((.+)%)%)$', '%1');
end
return str, 0 ~= count;
end
--[[--------------------------< S A F E _ F O R _ I T A L I C S >----------------------------------------------
Protects a string that will be wrapped in wiki italic markup '' ... ''
Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that
they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact
poorly under Mediawiki's HTML tidy.
]]
local function safe_for_italics (str)
if not is_set (str) then return str end
if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end
if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end
-- Remove newlines as they break italics.
return str:gsub ('\n', ' ');
end
--[[--------------------------< W R A P _ S T Y L E >----------------------------------------------------------
Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one
argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason
this function is similar to but separate from wrap_msg().
]]
local function wrap_style (key, str)
if not is_set (str) then
return '';
elseif in_array (key, cfg.presentation['_safe_for_italics']) then
str = safe_for_italics (str);
end
return substitute (cfg.presentation[key], str);
end
--[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------
make a separated list of items using provided separators.
<sep_list> - typically '<comma><space>'
<sep_list_pair> - typically '<space>and<space>'
<sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>'
defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']
if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied
]]
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)
local list = '';
if not sep_list then -- set the defaults
sep_list = cfg.presentation['sep_list'];
sep_list_pair = cfg.presentation['sep_list_pair'];
sep_list_end = cfg.presentation['sep_list_end'];
end
if 2 >= count then
list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item
elseif 2 < count then
list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator
list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator
end
return list;
end
--[[--------------------------< S A F E _ J O I N >------------------------------------------------------------
Joins a sequence of strings together while checking for duplicate separation characters.
]]
local function safe_join( tbl, duplicate_char )
--[[
Note: we use string functions here, rather than ustring functions.
This has considerably faster performance and should work correctly as
long as the duplicate_char is strict ASCII. The strings
in tbl may be ASCII or UTF8.
]]
local str = ''; -- the output string
local comp = ''; -- what does 'comp' mean?
local end_chr = '';
local trim;
for _, value in ipairs( tbl ) do
if value == nil then value = ''; end
if str == '' then -- if output string is empty
str = value; -- assign value to it (first time through the loop)
elseif value ~= '' then
if value:sub(1,1) == '<' then -- Special case of values enclosed in spans and other markup.
comp = value:gsub( "%b<>", "" ); -- remove html markup (<span>string</span> -> string)
else
comp = value;
end
-- typically duplicate_char is sepc
if comp:sub(1,1) == duplicate_char then -- is first charactier same as duplicate_char? why test first character?
-- Because individual string segments often (always?) begin with terminal punct for th
-- preceding segment: 'First element' .. 'sepc next element' .. etc?
trim = false;
end_chr = str:sub(-1,-1); -- get the last character of the output string
-- str = str .. "<HERE(enchr=" .. end_chr.. ")" -- debug stuff?
if end_chr == duplicate_char then -- if same as separator
str = str:sub(1,-2); -- remove it
elseif end_chr == "'" then -- if it might be wikimarkup
if str:sub(-3,-1) == duplicate_char .. "''" then -- if last three chars of str are sepc''
str = str:sub(1, -4) .. "''"; -- remove them and add back ''
elseif str:sub(-5,-1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]''
trim = true; -- why? why do this and next differently from previous?
elseif str:sub(-4,-1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]''
trim = true; -- same question
end
elseif end_chr == "]" then -- if it might be wikimarkup
if str:sub(-3,-1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink
trim = true;
elseif str:sub(-2,-1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link
trim = true;
elseif str:sub(-4,-1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title.
trim = true;
end
elseif end_chr == " " then -- if last char of output string is a space
if str:sub(-2,-1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space>
str = str:sub(1,-3); -- remove them both
end
end
if trim then
if value ~= comp then -- value does not equal comp when value contains html markup
local dup2 = duplicate_char;
if dup2:match( "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it
value = value:gsub( "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows html markup
else
value = value:sub( 2, -1 ); -- remove duplicate_char when it is first character
end
end
end
str = str .. value; --add it to the output string
end
end
return str;
end
--[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >--------------------------------
Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata.
This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to
markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind.
]]
local function strip_apostrophe_markup (argument)
if not is_set (argument) then return argument; end
while true do
if argument:match ("%'%'%'%'%'") then -- bold italic (5)
argument=argument:gsub("%'%'%'%'%'", ""); -- remove all instances of it
elseif argument:match ("%'%'%'%'") then -- italic start and end without content (4)
argument=argument:gsub("%'%'%'%'", "");
elseif argument:match ("%'%'%'") then -- bold (3)
argument=argument:gsub("%'%'%'", "");
elseif argument:match ("%'%'") then -- italic (2)
argument=argument:gsub("%'%'", "");
else
break;
end
end
return argument; -- done
end
--[[--------------------------< H A S _ I N V I S I B L E _ C H A R S >----------------------------------------
This function searches a parameter's value for nonprintable or invisible characters. The search stops at the
first match.
This function will detect the visible replacement character when it is part of the wikisource.
Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers (gallery, math, pre, ref)
and identifies them with a slightly different error message. See also coins_cleanup().
Detects but ignores the character pattern that results from the transclusion of {{'}} templates.
Output of this function is an error message that identifies the character or the Unicode group, or the stripmarker
that was detected along with its position (or, for multi-byte characters, the position of its first byte) in the
parameter value.
]]
local function has_invisible_chars (param, v)
local position = ''; -- position of invisible char or starting position of stripmarker
local dummy; -- end of matching string; not used but required to hold end position when a capture is returned
local capture; -- used by stripmarker detection to hold name of the stripmarker
local i=1;
local stripmarker, apostrophe;
while cfg.invisible_chars[i] do
local char=cfg.invisible_chars[i][1] -- the character or group name
local pattern=cfg.invisible_chars[i][2] -- the pattern used to find it
position, dummy, capture = mw.ustring.find (v, pattern) -- see if the parameter value contains characters that match the pattern
if position then
if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition)
('templatestyles' == capture) then -- templatestyles stripmarker allowed
stripmarker = true; -- set a flag
elseif true == stripmarker and 'delete' == char then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
position = nil; -- unset
elseif 'apostrophe' == char then -- apostrophe template uses ‍, hair space and zero-width space
apostrophe = true;
elseif true == apostrophe and in_array (char, {'zero width joiner', 'zero width space', 'hair space'}) then
position = nil; -- unset
else
local err_msg;
if capture then
err_msg = capture .. ' ' .. cfg.invisible_chars[i][3] or char;
else
err_msg = cfg.invisible_chars[i][3] or (char .. ' character');
end
return {err_msg, wrap_style ('parameter', param), position}; -- and done with this parameter
end
end
i=i+1; -- bump our index
end
end
--[[--------------------------< W R A P _ M S G >--------------------------------------------------------------
Applies additional message text to various parameter values. Supplied string is wrapped using a message_list
configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken
from citation_config.messages - the reason this function is similar to but separate from wrap_style().
]]
local function wrap_msg (key, str, lower)
if not is_set (str) then
return '';
elseif in_array (key, cfg.messages['_safe_for_italics']) then
str = safe_for_italics (str);
end
if true == lower then
local msg;
msg = cfg.messages[key]:lower(); -- set the message to lower case before
return substitute (msg, str); -- including template text
else
return substitute (cfg.messages[key], str);
end
end
--[[--------------------------< K E R N _ Q U O T E S >--------------------------------------------------------
Apply kerning to open the space between the quote mark provided by the Module and a leading or trailing quote mark contained in a |title= or |chapter= parameter's value.
This function will positive kern either single or double quotes:
"'Unkerned title with leading and trailing single quote marks'"
" 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example)
Double single quotes (italic or bold wikimarkup) are not kerned.
Call this function for chapter titles, for website titles, etc; not for book titles.
]]
local function kern_quotes (str)
local cap='';
local cap2='';
cap, cap2 = str:match ("^([\"\'])([^\'].+)"); -- match leading double or single quote but not double single quotes
if is_set (cap) then
str = wrap_style ('kern-left', {cap, cap2});
end
cap, cap2 = str:match ("^(.+[^\'])([\"\'])$")
if is_set (cap) then
str = wrap_style ('kern-right', {cap, cap2});
end
return str;
end
--[[--------------------------< P E N D _ S E P A R A T O R >--------------------------------------------------
]]
local function pend_separator (item, sepc, prepend)
if prepend then
return is_set (item) and sepc .. ' ' .. item or '';
else
return is_set (item) and item .. sepc .. ' ' or '';
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr)
cfg = cfg_table_ptr;
end
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
first_set = first_set, -- exported functions
has_accept_as_written = has_accept_as_written,
has_invisible_chars = has_invisible_chars,
hyphen_to_dash = hyphen_to_dash,
in_array = in_array,
is_set = is_set,
kern_quotes = kern_quotes,
make_sep_list = make_sep_list,
pend_separator = pend_separator,
safe_join = safe_join,
substitude = substitude,
strip_apostrophe_markup = strip_apostrophe_markup,
substitute = substitute,
wrap_style = wrap_style,
wrap_msg = wrap_msg,
set_selected_modules = set_selected_modules
}
348e3c9fd18b1f4d98186b6f2bce91911d81505b
Module:Citation/CS1/Error
828
199
416
2022-04-26T16:36:02Z
zhwp>Antigng
0
已保护“[[Module:Citation/CS1/Error]]”:[[WP:HRT|高风险模块]]([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
--[[
本模块包含了与CS1模块所需,与错误/维护信息相关的函数。错误/维护信息及相关的追踪分类存放于本模块定义的表z中。
请留意过去本站及当前的英文站相应的模块中,该表曾导出供其它模块使用;现已取消。
请勿在其它模块中直接使用或操作表z。由于不兼容性,请勿直接使用英文站模块中定义、和表z有关的函数。
目前该模块导出8个函数,其中:
add_maint_cat()和add_prop_cat()分别用于向表z添加配置模块中定义的"引文格式1维护"分类和"CS1屬性"分类
set_error()和append_error()的用途都是向表z添加配置模块中定义的"引文格式1错误"分类,同时生成一条报错信息;
前者会将该条信息作为返回值输出,后者则直接将该条信息插入表z中。
主模块最后会调用make_error_tail(),在引文的尾部集中输出存储于表z的有关信息。
因此,如报错信息需显示在引文中部,应使用set_error(),并手动将其返回的报错信息插入引文中部;
如报错信息可集中显示在引文尾部,只需使用append_error()即可。
reset_error()用于清除表z中指定的信息。
select_one()用于在多个可能有效的参数中挑选一个,如多于一个参数有效会自动报"xx与yy与zz...只需其一"错误。
throw_error()产生一条配置模块中定义的"内部错误"信息,并终止程序。
]]
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local z = {
error_categories = {}; -- for categorizing citations that contain errors
error_ids = {};
message_tail = {};
maintenance_cats = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
properties_cats = {}; -- for categorizing citations based on certain properties, language of source for instance
};
local cfg;
local in_array, is_set, substitute, wrap_style;
local make_internal_link;
--[[--------------------------< T H R O W _ E R R O R >-------------------------------------------------------
Terminate the program with a pre-defined excuse.
]]
local function throw_error (arg)
error (cfg.internal_errors[arg]);
end
--[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------
Wraps error messages with css markup according to the state of hidden.
]]
local function error_comment (content, hidden)
return wrap_style (hidden and 'hidden-error' or 'visible-error', content);
end
--[[--------------------------< S E T _ E R R O R >--------------------------------------------------------------
Sets an error condition and returns the appropriate error message. The actual placement of the error message in the output is
the responsibility of the calling function.
]]
local added_error_cats = {};
local function set_error (error_id, arguments, raw, prefix, suffix)
local error_state = cfg.error_conditions[error_id];
prefix = prefix or '';
suffix = suffix or '';
if error_state == nil then
throw_error ('undefined_error');
elseif is_set (error_state.category) then
local category = substitute (error_state.category, arguments);
if not added_error_cats[error_id] then
table.insert (z.error_categories, category)
added_error_cats[error_id] = true; -- note that we've added this category
end
end
local message = substitute (error_state.message, arguments);
message = table.concat (
{
message,
' (',
make_internal_link (
table.concat (
{
cfg.messages['help page link'],
'#',
error_state.anchor
}),
cfg.messages['help page label']),
')'
});
z.error_ids[error_id] = true;
if in_array (error_id, {'bare_url_missing_title', 'trans_missing_title'})
and z.error_ids['citation_missing_title'] then
return '', false;
end
message = table.concat ({prefix, message, suffix});
if raw == true then
return message, error_state.hidden;
end
return error_comment (message, error_state.hidden);
end
--[[--------------------------< A P P E N D _ E R R O R >--------------------------------------------------------
Sets an error condition, then appends the appropriate error message to z.message_tail.
]]
local function append_error (error_id, arguments, prefix, suffix)
table.insert (z.message_tail, {set_error (error_id, arguments, true, prefix, suffix)});
end
--[[-------------------------< I S _ A L I A S _ U S E D >-----------------------------------------------------
This function is used by select_one() to determine if one of a list of alias parameters is in the argument list
provided by the template.
Input:
args – pointer to the arguments table from calling template
alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
index – for enumerated parameters, identifies which one
enumerated – true/false flag used to choose how enumerated aliases are examined
value – value associated with an alias that has previously been selected; nil if not yet selected
selected – the alias that has previously been selected; nil if not yet selected
error_list – list of aliases that are duplicates of the alias already selected
Returns:
value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected
selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected
]]
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)
if enumerated then -- is this a test for an enumerated parameters?
alias = alias:gsub ('#', index); -- replace '#' with the value in index
else
alias = alias:gsub ('#', ''); -- remove '#' if it exists
end
if is_set (args[alias]) then -- alias is in the template's argument list
if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
local skip;
for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias
if v == alias then
skip = true;
break; -- has been added so stop looking
end
end
if not skip then -- has not been added so
table.insert (error_list, alias); -- add error alias to the error list
end
else
value = args[alias]; -- not yet selected an alias, so select this one
selected = alias;
end
end
return value, selected; -- return newly selected alias, or previously selected alias
end
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
Adds a category to z.maintenance_cats using names from the configuration file with additional text if any.
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maintenance_cats.
]]
local added_maint_cats = {};
local function add_maint_cat (key, arguments)
if not added_maint_cats [key] then
added_maint_cats [key] = true; -- note that we've added this category
table.insert (z.maintenance_cats, substitute (cfg.maint_cats [key], arguments));
-- make name then add to table
end
end
--[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
Adds a category to z.properties_cats using names from the configuration file with additional text if any.
]]
local added_prop_cats = {} -- list of property categories that have been added to z.properties_cats
local function add_prop_cat (key, arguments)
if not added_prop_cats [key] then
added_prop_cats [key] = true; -- note that we've added this category
table.insert (z.properties_cats, substitute (cfg.prop_cats [key], arguments));
-- make name then add to table
end
end
--[[--------------------------< S E L E C T _ O N E >----------------------------------------------------------
Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just
names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified
by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'.
Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities.
Generates an error if more than one match is present.
]]
local function select_one (args, aliases_list, error_condition, index)
local value = nil; -- the value assigned to the selected parameter
local selected = ''; -- the name of the parameter we have chosen
local error_list = {};
if index ~= nil then index = tostring (index); end
for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list
if alias:match ('#') then -- if this alias can be enumerated
if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
end
value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
else
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); --test for non-enumerated alias
end
end
if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
local error_str = '';
for _, k in ipairs (error_list) do
if error_str ~= '' then error_str = error_str .. cfg.messages['parameter-separator'] end
error_str = error_str .. wrap_style ('parameter', k);
end
if #error_list > 1 then
error_str = error_str .. cfg.messages['parameter-final-separator'];
else
error_str = error_str .. cfg.messages['parameter-pair-separator'];
end
error_str = error_str .. wrap_style ('parameter', selected);
append_error (error_condition, {error_str});
end
return value, selected;
end
--[[--------------------------< M A K E _ E R R O R _ T A I L >--------------------------------------------------
The function generates error/maintenance-related messages and/or tracking categories from "z" defined in this module.
]]
local function make_error_tail (flag)
local error_text = '';
if #z.message_tail ~= 0 then
error_text = ' ';
for i,v in ipairs (z.message_tail) do
if is_set (v[1]) then
if i == #z.message_tail then
error_text = error_text .. error_comment (v[1], v[2]);
else
error_text = error_text .. error_comment (v[1] .. '; ', v[2]);
end
end
end
end
if #z.maintenance_cats ~= 0 then
local maintenance_text = '';
for _, v in ipairs (z.maintenance_cats) do -- append maintenance categories
maintenance_text = maintenance_text .. substitute (cfg.messages['maintenance-item'], {v, make_internal_link (':Category:' .. v, cfg.messages['maintenance-link'])})
end
error_text = error_text .. wrap_style ('maintenance', maintenance_text);
-- maintenance mesages (realy just the names of the categories for now)
end
if not flag then
for _, v in ipairs (z.error_categories) do
error_text = error_text .. make_internal_link ('Category:' .. v);
end
for _, v in ipairs (z.maintenance_cats) do -- append maintenance categories
error_text = error_text .. make_internal_link ('Category:' .. v);
end
for _, v in ipairs (z.properties_cats) do -- append maintenance categories
error_text = error_text .. make_internal_link ('Category:' .. v);
end
end
return error_text;
end
--[[--------------------------< R E S E T _ E R R O R >-------------------------------------------------------
Reset error/maintenance messages/categories in z.
]]
local function reset_error (args)
if (in_array ('err_cats', args)) then
z.error_categories = {};
end
if (in_array ('prop_cats', args)) then
z.properties_cats = {};
end
if (in_array ('maint_cats', args)) then
z.maintenance_cats = {};
end
if (in_array ('err_ids', args)) then
z.error_ids = {};
end
if (in_array ('msg_tail', args)) then
z.message_tail = {};
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
in_array = utilities_page_ptr.in_array;
is_set = utilities_page_ptr.is_set;
substitute = utilities_page_ptr.substitute;
wrap_style= utilities_page_ptr.wrap_style;
make_internal_link = links_page_ptr.make_internal_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
add_maint_cat = add_maint_cat, -- exported functions
add_prop_cat = add_prop_cat,
append_error = append_error,
make_error_tail = make_error_tail,
reset_error = reset_error,
select_one = select_one,
set_error = set_error,
throw_error = throw_error,
set_selected_modules = set_selected_modules
}
72c70434eb1bad858e4ea121f07809f6cb76c9f9
Module:Citation/CS1/Links
828
200
418
2022-04-26T16:36:50Z
zhwp>Antigng
0
已保护“[[Module:Citation/CS1/Links]]”:[[WP:HRT|高风险模块]]([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
--[[
本模块用于处理维基内链和外链。目前导出四个函数:
check_for_external_link()用于批量检查参数中可能存在的外链。
make_external_link()依据输入的url参数和"显示"参数输出维基外链,
并对其中url参数的格式进行检查。若查出url格式不正确,
在设定"源"参数的情况下,会根据该参数产生"引文格式1错误"信息,
附于生成的外链后方;如"源"参数未设定,则会抛出内部错误终止程序。
make_internal_link()依据输入的"目标页面"参数和"显示"参数输出维基内链,
并对其中"目标页面"参数的格式稍加检查。
若查出"目标页面"格式不正确(例如:含有页面标题中不允许出现的字符),
在设定"源"参数的情况下,会根据该参数产生"引文格式1错误"信息,
该条信息被其它模块处理后会显示于引文的尾部;
如"源"参数未设定,则会抛出内部错误终止程序。
以上两个函数既可用于处理模板参数,也可用于转换配置模块中的有关参数。
但请注意,用于前者时必须指定"源"参数(即被处理的参数名称)并保证其值有效,
用于后者时必须确保配置文件模块编写正确。否则将导致Lua错误!
remove_wiki_link()用于移除维基内链。
]]
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set;
local append_error, set_error, throw_error;
--[[--------------------------< I S _ S C H E M E >------------------------------------------------------------
does this thing that purports to be a uri scheme seem to be a valid scheme? The scheme is checked to see if it
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:
Scheme names consist of a sequence of characters beginning with a
letter and followed by any combination of letters, digits, plus
("+"), period ("."), or hyphen ("-").
returns true if it does, else false
]]
local function is_scheme (scheme)
return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern
end
--[=[-------------------------< I S _ D O M A I N _ N A M E >--------------------------------------------------
Does this thing that purports to be a domain name seem to be a valid domain name?
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5
BNF defined here: https://tools.ietf.org/html/rfc4234
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;
see also [[Single-letter second-level domain]]
list of tlds: https://www.iana.org/domains/root/db
rfc952 (modified by rfc 1123) requires the first and last character of a hostname to be a letter or a digit. Between
the first and last characters the name may use letters, digits, and the hyphen.
Also allowed are IPv4 addresses. IPv6 not supported
domain is expected to be stripped of any path so that the last character in the last character of the tld. tld
is two or more alpha characters. Any preceding '//' (from splitting a url with a scheme) will be stripped
here. Perhaps not necessary but retained incase it is necessary for IPv4 dot decimal.
There are several tests:
the first character of the whole domain name including subdomains must be a letter or a digit
single-letter/digit second-level domains in the .org TLD
q, x, and z SL domains in the .com TLD
i and q SL domains in the .net TLD
single-letter SL domains in the ccTLDs (where the ccTLD is two letters)
two-character SL domains in gTLDs (where the gTLD is two or more letters)
three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)
IPv4 dot-decimal address format; TLD not allowed
returns true if domain appears to be a proper name and tld or IPv4 address, else false
]=]
local function is_domain_name (domain)
if not domain then
return false; -- if not set, abandon
end
domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once
if not domain:match ('^[%a%d]') then -- first character must be letter or digit
return false;
end
if domain:match ('%f[%a%d][%a%d]%.org$') then -- one character .org hostname
return true;
elseif domain:match ('%f[%a][qxz]%.com$') then -- assigned one character .com hostname (x.com times out 2015-12-10)
return true;
elseif domain:match ('%f[%a][iq]%.net$') then -- assigned one character .net hostname (q.net registered but not active 2015-12-10)
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$') then -- internationalized domain name with ACE prefix
return true;
elseif domain:match ('%f[%a%d][%a%d]%.cash$') then -- one character/digit .cash hostname
return true;
elseif domain:match ('%f[%a%d][%a%d]%.%a%a$') then -- one character hostname and cctld (2 chars)
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d]%.%a%a+$') then -- two character hostname and tld
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.%a%a+$') then -- three or more character hostname.hostname or hostname.tld
return true;
elseif domain:match ('^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?') then -- IPv4 address
return true;
else
return false;
end
end
--[[--------------------------< I S _ U R L >------------------------------------------------------------------
returns true if the scheme and domain parts of a url appear to be a valid url; else false.
This function is the last step in the validation process. This function is separate because there are cases that
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external
wikilinks.
]]
local function is_url (scheme, domain)
if is_set (scheme) then -- if scheme is set check it and domain
return is_scheme (scheme) and is_domain_name (domain);
else
return is_domain_name (domain); -- scheme not set when url is protocol relative
end
end
--[[--------------------------< S P L I T _ U R L >------------------------------------------------------------
Split a url into a scheme, authority indicator, and domain.
If protocol relative url, return nil scheme and domain else return nil for both scheme and domain.
When not protocol relative, get scheme, authority indicator, and domain. If there is an authority indicator (one
or more '/' characters following the scheme's colon), make sure that there are only 2.
]]
local function split_url (url_str)
local scheme, authority, domain;
url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//')
if url_str:match ('^//%S*') then -- if there is what appears to be a protocol relative url
domain = url_str:match ('^//(%S*)')
elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name
scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions
authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing;
if is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then
return scheme; -- return scheme only making domain nil which will cause an error message
end
domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present
end
return scheme, domain;
end
--[[--------------------------< L I N K _ P A R A M _ O K >---------------------------------------------------
checks the content of |title-link=, |series-link=, |author-link= etc for properly formatted content: no wikilinks, no urls
Link parameters are to hold the title of a wikipedia article so none of the WP:TITLESPECIALCHARACTERS are allowed:
# < > [ ] | { } _
except the underscore which is used as a space in wiki urls and # which is used for section links
returns false when the value contains any of these characters.
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid url (the
|<param>-link= parameter is ok); else false when value appears to be a valid url (the |<param>-link= parameter is NOT ok).
]]
local function link_param_ok (value)
local scheme, domain;
if value:find ('[<>%[%]|{}]') then -- if any prohibited characters
return false;
end
scheme, domain = split_url (value); -- get scheme or nil and domain or nil from url;
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid url
end
--[=[-------------------------< M A K E _ I N T E R N A L _ L I N K >------------------------------------------
Format a wikilink with error checking; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided (or link and display are the same), returns a wikilink in the form [[L]].
]=]
local function make_internal_link (link, display, source)
if not link_param_ok (link) then
if is_set (source) then
append_error ('bad_paramlink', {source});
else
throw_error('bad_link_no_origin');
end
end
if is_set (display) and link ~= display then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
end
--[=[-------------------------< R E M O V E _ W I K I _ L I N K >----------------------------------------------
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label
if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match
in the initial gsub, the replacement function l() doesn't get called.
]=]
local function remove_wiki_link (str)
return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l)
return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1");
end));
end
--[=[-------------------------< I S _ W I K I L I N K >--------------------------------------------------------
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.
If str is a complex wikilink ([[L|D]]):
returns wl_type 2 and D and L from [[L|D]];
if str is a simple wikilink ([[D]])
returns wl_type 1 and D from [[D]] and L as empty string;
if not a wikilink:
returns wl_type 0, str as D, and L as empty string.
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).
]=]
local function is_wikilink (str)
local D, L
local wl_type = 2; -- assume that str is a complex wikilink [[L|D]]
if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content)
return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L
end
L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]]
if not is_set (D) then -- if no separate display
D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]]
wl_type = 1;
end
D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters
return wl_type, D, L or '';
end
--[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------
Escape sequences for content that will be used for URL descriptions
]]
local function safe_for_url( str )
if str:match( "%[%[.-%]%]" ) ~= nil then
append_error( 'wikilink_in_url', {});
end
return str:gsub( '[%[%]\n]', {
['['] = '[',
[']'] = ']',
['\n'] = ' ' } );
end
--[[--------------------------< C H E C K _ U R L >------------------------------------------------------------
Determines whether a URL string appears to be valid.
First we test for space characters. If any are found, return false. Then split the url into scheme and domain
portions, or for protocol relative (//example.com) urls, just the domain. Use is_url() to validate the two
portions of the url. If both are valid, or for protocol relative if domain is valid, return true, else false.
]]
local function check_url( url_str )
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper url
return false;
end
local scheme, domain;
scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from url;
return is_url (scheme, domain); -- return true if value appears to be a valid url
end
--[[--------------------------< M A K E _ E X T E R N A L _ L I N K >--------------------------------------------
Format an external link with error checking
]]
local function make_external_link( URL, label, source )
local error_str = "";
if not is_set( label ) then
label = URL;
if is_set( source ) then
error_str = set_error( 'bare_url_missing_title', source, false, " " );
else
throw_error( 'bare_url_no_origin' );
end
end
if not check_url( URL ) then
if is_set ( source ) then
error_str = set_error( 'bad_url', source, false, " " ) .. error_str;
else
throw_error( 'bad_url_no_origin' );
end
end
return table.concat({ "[", URL, " ", safe_for_url( label ), "]", error_str });
end
--[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
non-space characters following the opening bracket appear to be a url. The test will also find external wikilinks
that use protocol relative urls. Also finds bare urls.
The frontier pattern prevents a match on interwiki links which are similar to scheme:path urls. The tests that
find bracketed urls are required because the parameters that call this test (currently |title=, |chapter=, |work=,
and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]]
is possible as might be [[en://Hus]].
]=]
local function is_parameter_ext_wikilink (value)
local scheme, domain;
value = value:gsub ('([^%s/])/[%a%d].*', '%1'); -- strip path information (the capture prevents false replacement of '//')
if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext wikilink with scheme and domain: [xxxx://yyyyy.zzz]
scheme, domain = value:match ('%f[%[]%[(%a%S*:)(%S+).*%]')
elseif value:match ('%f[%[]%[//%S*%.%S+.*%]') then -- if protocol relative ext wikilink: [//yyyyy.zzz]
domain = value:match ('%f[%[]%[//(%S*%.%S+).*%]');
elseif value:match ('%a%S*:%S+') then -- if bare url with scheme; may have leading or trailing plain text
scheme, domain = value:match ('(%a%S*:)(%S+)');
elseif value:match ('//%S*%.%S+') then -- if protocol relative bare url: //yyyyy.zzz; may have leading or trailing plain text
domain = value:match ('//(%S*%.%S+)'); -- what is left should be the domain
else
return false; -- didn't find anything that is obviously a url
end
return is_url (scheme, domain); -- return true if value appears to be a valid url
end
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message.
]]
local function check_for_external_link (parameter_list)
local error_message = '';
for k, v in pairs (parameter_list) do -- for each parameter in the list
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a url add an error message
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "|" .. k .. "="; -- add the failed parameter
end
end
if is_set (error_message) then -- done looping, if there is an error message, display it
append_error( 'param_has_ext_link', {error_message});
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Import some functions from Module:Citation/CS1/Utilities and Module:Citation/CS1/Error
]]
local function set_selected_modules (utilities_page_ptr, error_page_ptr)
is_set = utilities_page_ptr.is_set;
append_error = error_page_ptr.append_error;
set_error = error_page_ptr.set_error;
throw_error = error_page_ptr.throw_error;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
check_for_external_link = check_for_external_link, -- exported functions
make_external_link = make_external_link,
make_internal_link = make_internal_link,
remove_wiki_link = remove_wiki_link,
set_selected_modules = set_selected_modules
}
662c9e35ee3704a0dda91f09654ce9e41fbeb9a4
Module:Citation/CS1/People
828
204
426
2022-04-26T16:37:18Z
zhwp>Antigng
0
已保护“[[Module:Citation/CS1/People]]”:[[WP:HRT|高风险模块]]([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg;
local in_array, is_set;
local append_error, add_maint_cat, select_one;
local make_internal_link;
--[[--------------------------< A D D _ V A N C _ E R R O R >----------------------------------------------------
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist.
To prevent duplication, added_vanc_errs is nil until an error message is emitted.
]]
local added_vanc_errs = false; -- flag so we only emit one Vancouver error / category
local function add_vanc_error ()
if not added_vanc_errs then
added_vanc_errs = true; -- note that we've added this category
append_error( 'vancouver', {});
end
end
--[[--------------------------< I S _ G O O D _ V A N C _ N A M E >--------------------------------------------
For Vancouver Style, author/editor names are supposed to be rendered in Latin (read ASCII) characters. When a name
uses characters that contain diacritical marks, those characters are to converted to the corresponding Latin character.
When a name is written using a non-Latin alphabet or logogram, that name is to be transliterated into Latin characters.
These things are not currently possible in this module so are left to the editor to do.
This test allows |first= and |last= names to contain any of the letters defined in the four Unicode Latin character sets
[http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A
[http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF
[http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F
[http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F
|lastn= also allowed to contain hyphens, spaces, and apostrophes. (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
|firstn= also allowed to contain hyphens, spaces, apostrophes, and periods
At the time of this writing, I had to write the 'if nil == mw.ustring.find ...' test ouside of the code editor and paste it here
because the code editor gets confused between character insertion point and cursor position.
]]
local function is_good_vanc_name (last, first)
if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]*$") then
add_vanc_error ();
return false; -- not a string of latin characters; Vancouver required Romanization
end;
return true;
end
--[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------
Attempts to convert names to initials in support of |name-list-format=vanc.
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/.
Vancouver style requires family rank designations (Jr, II, III, etc) to be rendered as Jr, 2nd, 3rd, etc. This form is not
currently supported by this code so correctly formed names like Smith JL 2nd are converted to Smith J2. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/.
This function uses ustring functions because firstname initials may be any of the unicode Latin characters accepted by is_good_vanc_name ().
]]
local function reduce_to_initials(first)
if mw.ustring.match(first, "^%u%u$") then return first end; -- when first contains just two upper-case letters, nothing to do
local initials = {}
local i = 0; -- counter for number of initials
for word in mw.ustring.gmatch(first, "[^%s%.%-]+") do -- names separated by spaces, hyphens, or periods
table.insert(initials, mw.ustring.sub(word,1,1)) -- Vancouver format does not include full stops.
i = i + 1; -- bump the counter
if 2 <= i then break; end -- only two initials allowed in Vancouver system; if 2, quit
end
return table.concat(initials) -- Vancouver format does not include spaces.
end
--[[--------------------------< L I S T _ P E O P L E >-------------------------------------------------------
Formats a list of people (e.g. authors / editors)
]]
local function list_people(control, people, etal, list_name) -- TODO: why is list_name here? not used in this function
local sep;
local namesep;
local format = control.format
local maximum = control.maximum
local lastauthoramp = control.lastauthoramp;
local text = {}
if 'vanc' == format then -- Vancouver-like author/editor name styling?
sep = ','; -- name-list separator between authors is a comma
namesep = ' '; -- last/first separator is a space
else
sep = ';' -- name-list separator between authors is a semicolon
namesep = ', ' -- last/first separator is <comma><space>
end
if sep:sub(-1,-1) ~= " " then sep = sep .. " " end
if is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for authors
for i,person in ipairs(people) do
if is_set(person.last) then
local mask = person.mask
local one
local sep_one = sep;
if is_set (maximum) and i > maximum then
etal = true;
break;
elseif (mask ~= nil) then
local n = tonumber(mask)
if (n ~= nil) then
one = string.rep("—",n)
else
one = mask;
sep_one = " ";
end
else
one = person.last
local first = person.first
if is_set(first) then
if ( "vanc" == format ) then -- if vancouver format
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
if not person.corporate and is_good_vanc_name (one, first) then -- and name is all Latin characters; corporate authors not tested
first = reduce_to_initials(first) -- attempt to convert first name(s) to initials
end
end
one = one .. namesep .. first
end
if is_set(person.link) and person.link ~= control.page_name then
one = make_internal_link(person.link, one, person.origin); -- link author/editor if this page is not the author's/editor's page
end
end
table.insert( text, one )
table.insert( text, sep_one )
end
end
local count = #text / 2; -- (number of names + number of separators) divided by 2
if count > 0 then
if count > 1 and is_set(lastauthoramp) and not etal then
text[#text-2] = " & "; -- replace last separator with ampersand text
end
text[#text] = nil; -- erase the last separator
end
local result = table.concat(text) -- construct list
if etal and is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've go a last-first list and etal so add et al.
end
return result, count
end
--[[--------------------------< G E T _ D I S P L A Y _ A U T H O R S _ E D I T O R S >------------------------
Returns a number that may or may not limit the length of the author or editor name lists.
When the value assigned to |display-authors= is a number greater than or equal to zero, return the number and
the previous state of the 'etal' flag (false by default but may have been set to true if the name list contains
some variant of the text 'et al.').
When the value assigned to |display-authors= is the keyword 'etal', return a number that is one greater than the
number of authors in the list and set the 'etal' flag true. This will cause the list_people() to display all of
the names in the name list followed by 'et al.'
In all other cases, returns nil and the previous state of the 'etal' flag.
]]
local function get_display_authors_editors (max, count, list_name, etal)
if is_set (max) then
if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
max = count + 1; -- number of authors + 1 so display all author name plus et al.
etal = true; -- overrides value set by extract_names()
elseif max:match ('^%d+$') then -- if is a string of numbers
max = tonumber (max); -- make it a number
if max >= count and 'authors' == list_name then -- AUTHORS ONLY -- if |display-xxxxors= value greater than or equal to number of authors/editors
add_maint_cat ('disp_auth_ed', list_name);
end
else -- not a valid keyword or number
append_error( 'invalid_param_val', {'display-' .. list_name, max});
-- add error message
max = nil; -- unset
end
elseif 'authors' == list_name then -- AUTHORS ONLY need to clear implicit et al category
max = count + 1; -- number of authors + 1
end
return max, etal;
end
--[[--------------------------< N A M E _ H A S _ E T A L >----------------------------------------------------
Evaluates the content of author and editor name parameters for variations on the theme of et al. If found,
the et al. is removed, a flag is set to true and the function returns the modified name and the flag.
This function never sets the flag to false but returns it's previous state because it may have been set by
previous passes through this function or by the parameters |display-authors=etal or |display-editors=etal
]]
local function name_has_etal (name, etal, nocat)
if is_set (name) then -- name can be nil in which case just return
local etal_pattern = "[;,]? *[\"']*%f[%a][Ee][Tt] *[Aa][Ll][%.\"']*$" -- variations on the 'et al' theme
local others_pattern = "[;,]? *%f[%a]and [Oo]thers"; -- and alternate to et al.
if name:match (etal_pattern) then -- variants on et al.
name = name:gsub (etal_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
add_maint_cat ('etal'); -- and add a category if not already added
end
elseif name:match (others_pattern) then -- if not 'et al.', then 'and others'?
name = name:gsub (others_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
add_maint_cat ('etal'); -- and add a category if not already added
end
end
end
return name, etal; --
end
--[[--------------------------< E X T R A C T _ N A M E S >----------------------------------------------------
Gets name list from the input arguments
Searches through args in sequential order to find |lastn= and |firstn= parameters (or their aliases), and their matching link and mask parameters.
Stops searching when both |lastn= and |firstn= are not found in args after two sequential attempts: found |last1=, |last2=, and |last3= but doesn't
find |last4= and |last5= then the search is done.
This function emits an error message when there is a |firstn= without a matching |lastn=. When there are 'holes' in the list of last names, |last1= and |last3=
are present but |last2= is missing, an error message is emitted. |lastn= is not required to have a matching |firstn=.
When an author or editor parameter contains some form of 'et al.', the 'et al.' is stripped from the parameter and a flag (etal) returned
that will cause list_people() to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps 'et al.' out of the
template's metadata. When this occurs, the page is added to a maintenance category.
]]
local function extract_names(args, list_name)
local names = {}; -- table of names
local last; -- individual name components
local first;
local link;
local mask;
local i = 1; -- loop counter/indexer
local n = 1; -- output table indexer
local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors)
local etal=false; -- return value set to true when we find some form of et al. in an author parameter
local err_msg_list_name = list_name:match ("(%w+)List") .. 's list'; -- modify AuthorList or EditorList for use in error messages if necessary
while true do
last = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1
first = select_one( args, cfg.aliases[list_name .. '-First'], 'redundant_parameters', i );
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i );
mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i );
last, etal = name_has_etal (last, etal, false); -- find and remove variations on et al.
first, etal = name_has_etal (first, etal, false); -- find and remove variations on et al.
if first and not last then -- if there is a firstn without a matching lastn
append_error( 'first_missing_last', {err_msg_list_name, i}); -- add this error message
elseif not first and not last then -- if both firstn and lastn aren't found, are we done?
count = count + 1; -- number of times we haven't found last and first
if 2 <= count then -- two missing names and we give up
break; -- normal exit or there is a two-name hole in the list; can't tell which
end
else -- we have last with or without a first
names[n] = {
last = last,
first = first,
link = link,
mask = mask,
origin = list_name:match ("(%w+)List"):lower() .. '-link' .. i,
corporate=false
}; -- add this name to our names list (corporate for |vauthors= only)
n = n + 1; -- point to next location in the names table
if 1 == count then -- if the previous name was missing
append_error( 'missing_name', {err_msg_list_name, i-1}); -- add this error message
end
count = 0; -- reset the counter, we're looking for two consecutive missing names
end
i = i + 1; -- point to next args location
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >--------------------------------
This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and
|xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does.
Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
tests, are wrapped in doubled paranethese ((corporate name)) to suppress the format tests.
This function sets the vancouver error when a reqired comma is missing and when there is a space between an author's initials.
]]
local function parse_vauthors_veditors (args, vparam, list_name)
local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn=
local v_name_table = {};
local etal = false; -- return value set to true when we find some form of et al. vauthors parameter
local last, first, link, mask;
local corporate = false;
vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period)
if vparam:find ('%[%[') or vparam:find ('%]%]') then -- no wikilinking vauthors names
add_vanc_error ();
end
v_name_table = mw.text.split(vparam, "%s*,%s*") -- names are separated by commas
for i, v_name in ipairs(v_name_table) do
if v_name:match ('^%(%(.+%)%)$') then -- corporate authors are wrapped in doubled parenthese to supress vanc formatting and error detection
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
last = v_name:match ('^%(%((.+)%)%)$')
corporate = true;
elseif string.find(v_name, "%s") then
lastfirstTable = {}
lastfirstTable = mw.text.split(v_name, "%s")
first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be author intials
last = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials
if mw.ustring.match (last, '%a+%s+%u+%s+%a+') or mw.ustring.match (v_name, ' %u %u$') then
add_vanc_error (); -- matches last II last; the case when a comma is missing or a space between two intiials
end
else
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this?
end
if is_set (first) and not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else
add_vanc_error ();
end
-- this from extract_names ()
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i );
mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i );
names[i] = {last = last, first = first, link = link, mask = mask, corporate=corporate}; -- add this assembled name to our names list
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< S E L E C T _ A U T H O R S _ E D I T O R S _ F R O M _ S O U R C E >------------------
Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or
select one of |editors=, |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list.
Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest and
similarly, |editorn= (and aliases) highest and |editors= lowest
When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second
test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better
way to do this, I just haven't discovered what that way is.
Emits an error message when more than one xxxxor name source is provided.
In this function, vxxxxors = vauthors or veditors; xxxxors = authors or editors as appropriate.
]]
local function select_authors_editors_from_source (vxxxxors, xxxxors, args, list_name, vparam, name_list_format)
local lastfirst = false;
if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a first 1 without a last1
select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) then
lastfirst = true;
end
if ( is_set ( vxxxxors ) and true == lastfirst ) or -- these are the three error conditions
( is_set ( vxxxxors ) and is_set ( xxxxors ) ) or
( lastfirst and is_set ( xxxxors ) ) then
local err_name;
if 'AuthorList' == list_name then -- figure out which name should be used in error message
err_name = 'author';
else
err_name = 'editor';
end
append_error( 'redundant_parameters', {err_name .. '-name-list parameters'});
-- add error message
end
local x, xxxxor_etal;
if not lastfirst then
if is_set ( vxxxxors ) then
x, xxxxor_etal = parse_vauthors_veditors ( args, vparam, list_name );
-- fetch author list from |vxxxxor=, |xxxxor-linkn=, and |xxxxor-maskn=
return x, xxxxor_etal, nil , 'vanc';
elseif is_set ( xxxxors ) then
return {}, nil, xxxxors, name_list_format; -- use content of |xxxxor=
end
end;
x, xxxxor_etal = extract_names ( args, list_name ); -- fetch xxxxor list from |xxxxorn= / |lastn= / |firstn=, |xxxxor-linkn=, and |xxxxor-maskn=, or
return x, xxxxor_etal, nil, name_list_format; -- no xxxxors at all; this allows missing xxxxor name test to run in case there is a first without last
end
local function get_people (handle, para, args, page_name)
local author_etal;
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors=
local Authors;
local NameListFormat = para.namelistformat;
a, author_etal, Authors, NameListFormat = select_authors_editors_from_source(
handle.vauthors,
handle.authors,
args,
'AuthorList',
args.vauthors,
NameListFormat
);
local Coauthors = handle.coauthors;
local editor_etal;
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors=
local Editors;
e, editor_etal, Editors, NameListFormat = select_authors_editors_from_source(
handle.veditors,
handle.editors,
args,
'EditorList',
args.veditors,
NameListFormat
);
local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs
local Translators; -- assembled translators name list
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
local Contributors; -- assembled contributors name list
local Contribution = handle.contribution;
if para.contributorsvalid then
c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn=
if 0 < #c then
if not is_set (Contribution) then -- |contributor= requires |contribution=
append_error( 'contributor_missing_required_param', {'contribution'});
-- add missing contribution error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
if 0 == #a then -- |contributor= requires |author=
append_error( 'contributor_missing_required_param', {'author'});-- add missing author error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
end
else -- if not a book cite
if select_one (args, cfg.aliases['ContributorList-Last'], 'redundant_parameters', 1 ) then -- are there contributor name list parameters?
append_error( 'contributor_ignored', {}); -- add contributor ignored error message
end
Contribution = nil; -- unset
end
local LastAuthorAmp = para.lastauthoramp;
if (in_array (NameListFormat, {'&', 'amp'})) then
LastAuthorAmp = 'yes'; -- override |lastauthoramp = if |name-list-format = is set to '&' or 'amp'
end
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list
do
local last_first_list;
local maximum;
local control = {
format = NameListFormat, -- empty string, 'vanc', or 'amp'
maximum = nil, -- as if display-authors or display-editors not set
lastauthoramp = LastAuthorAmp,
page_name = page_name -- get current page name so that we don't wikilink to it via editorlinkn
};
do -- do editor name list first because coauthors can modify control table
maximum , editor_etal = get_display_authors_editors (para.displayeditors, #e, 'editors', editor_etal);
--[[ Preserve old-style implicit et al.
临时修复"Category:含有旧式缩略标签的引用的页面 in editors"的问题,中文版目前与英文版逻辑不一样,暂时不需要这个分类。等以后更新时再看怎么处理 --2017.6.23 shizhao
if not is_set(maximum) and #e == 4 then
maximum = 3;
append_error('implict_etal_editor', {});
end
]]
control.maximum = maximum;
last_first_list, EditorCount = list_people(control, e, editor_etal, 'editor');
if is_set (Editors) then
if editor_etal then
Editors = Editors .. ' ' .. cfg.messages['et al']; -- add et al. to editors parameter beause |display-editors=etal
EditorCount = 2; -- with et al., |editors= is multiple names; spoof to display (eds.) annotation
else
EditorCount = 2; -- we don't know but assume |editors= is multiple names; spoof to display (eds.) annotation
end
else
Editors = last_first_list; -- either an author name list or an empty string
end
if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then
EditorCount = 2; -- spoof to display (eds.) annotation
end
end
do -- now do translators
control.maximum = #t; -- number of translators
Translators = list_people(control, t, false, 'translator'); -- et al not currently supported
end
do -- now do contributors
control.maximum = #c; -- number of contributors
Contributors = list_people(control, c, false, 'contributor'); -- et al not currently supported
end
do -- now do authors
control.maximum , author_etal = get_display_authors_editors (para.displayauthors, #a, 'authors', author_etal);
if is_set(Coauthors) then -- if the coauthor field is also used, prevent ampersand and et al. formatting.
para.lastauthoramp = nil;
control.maximum = #a + 1;
end
last_first_list = list_people(control, a, author_etal, 'author');
if is_set (Authors) then
Authors, author_etal = name_has_etal (Authors, author_etal, false); -- find and remove variations on et al.
if author_etal then
Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter
end
else
Authors = last_first_list; -- either an author name list or an empty string
end
end -- end of do
if is_set(Authors) then
if is_set(Coauthors) then
if 'vanc' == NameListFormat then -- separate authors and coauthors with proper name-list-separator
Authors = Authors .. ', ' .. Coauthors;
else
Authors = Authors .. '; ' .. Coauthors;
end
end
elseif is_set(Coauthors) then -- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specified
append_error('coauthors_missing_author', {}); -- emit error message
end
end
local multiple_editors = EditorCount >1;
local has_contributors = false;
local NameList = {}; -- holds selected contributor, author, editor name list
if #c > 0 then -- if there is a contributor list
NameList = c; -- select it
has_contributor = true;
elseif #a > 0 then -- or an author list
NameList = a;
elseif #e > 0 then -- or an editor list
NameList = e;
end
return Authors, Contributors, Editors, Translators, Contribution, NameList, multiple_editors, has_contributors;
end
--[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >----------------------------------------
This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space
when the last character is not a sepc character or when the last three characters are not sepc followed by two
closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a
single space character.
]]
local function terminate_name_list (name_list, sepc)
if (string.sub (name_list,-1,-1) == sepc) or (string.sub (name_list,-3,-1) == sepc .. ']]') then -- if last name in list ends with sepc char
return name_list .. " "; -- don't add another
else
return name_list .. sepc .. ' '; -- otherwise terninate the name list
end
end
--[[--------------------------< F O R M A T _ P E O P L E >------------------------------------------------
]]
local function format_people (Authors, Editors, Contributors, multiple_editors, use_in, sepc)
if is_set (Authors) then
Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space
if is_set (Editors) then
local in_text = " ";
local post_text = "";
if use_in then
in_text = in_text .. " " .. cfg.messages['in'];
if (sepc ~= '.') then in_text = in_text:lower() end -- lowercase for cs2
else
if multiple_editors then
post_text = ", " .. cfg.messages['editors'];
else
post_text = ", " .. cfg.messages['editor'];
end
end
Editors = terminate_name_list (Editors .. in_text .. post_text, sepc);
-- terminate with 0 or 1 sepc and a space
end
if is_set (Contributors) then -- book cite and we're citing the intro, preface, etc
local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' ';
if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2
Authors = by_text .. Authors; -- author follows title so tweak it here
if is_set (Editors) then -- when Editors make sure that Authors gets terminated
Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space
end
Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space
end
else
if is_set (Editors) then
if multiple_editors then
Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " "
else
Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "
end
end
end
return Authors, Editors, Contributors;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, error_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
add_maint_cat = error_page_ptr.add_maint_cat;
append_error = error_page_ptr.append_error;
select_one = error_page_ptr.select_one;
make_internal_link = links_page_ptr.make_internal_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
get_people = get_people,
format_people = format_people,
set_selected_modules = set_selected_modules
}
34b4459f64df67c8563c0ec14c8ddfbba8196c57
Module:Citation/CS1/COinS
828
205
428
2022-04-26T16:37:55Z
zhwp>Antigng
0
已保护“[[Module:Citation/CS1/COinS]]”:[[WP:HRT|高风险模块]]([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities and Module:Citation/CS1/Links
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< M A K E _ C O I N S _ T I T L E >----------------------------------------------
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings
of %27%27...
]]
local function make_coins_title (title, script)
if is_set (title) then
title = strip_apostrophe_markup (title); -- strip any apostrophe markup
else
title = ''; -- if not set, make sure title is an empty string
end
if is_set (script) then
script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string)
script = strip_apostrophe_markup (script); -- strip any apostrophe markup
else
script = ''; -- if not set, make sure script is an empty string
end
if is_set (title) and is_set (script) then
script = ' ' .. script; -- add a space before we concatenate
end
return title .. script; -- return the concatenation
end
--[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------
Returns a string where all of Lua's magic characters have been escaped. This is important because functions like
string.gsub() treat their pattern and replace strings as patterns, not literal strings.
]]
local function escape_lua_magic_chars (argument)
argument = argument:gsub("%%", "%%%%"); -- replace % with %%
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters
return argument;
end
--[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.
]]
local function get_coins_pages (pages)
local pattern;
if not is_set (pages) then return pages; end -- if no page numbers then we're done
while true do
pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url "
if nil == pattern then break; end -- no more URLs
pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters
pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible
end
pages = pages:gsub("[%[%]]", ""); -- remove the brackets
pages = pages:gsub("–", "-" ); -- replace endashes with hyphens
pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (– etc.) with hyphens; do we need to replace numerical entities like   and the like?
return pages;
end
--[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------
There are three options for math markup rendering that depend on the editor's math preference settings. These
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are
PNG images
TeX source
MathML with SVG or PNG fallback
All three are heavy with HTML and CSS which doesn't belong in the metadata.
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings
of the last editor to save the page.
This function gets the rendered form of an equation according to the editor's preference before the page is saved. It
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial
value. To replace multipe equations it is necessary to call this function from within a loop.
]=]
local function coins_replace_math_stripmarker (value)
local stripmarker = cfg.stripmarkers['math'];
local rendering = value:match (stripmarker); -- is there a math stripmarker
if not rendering then -- when value doesn't have a math stripmarker, abandon this test
return false, value;
end
rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error)
if rendering:match ('alt="[^"]+"') then -- if PNG math option
rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text
elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$
rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text
elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option
rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text
else
return false, value; -- had math stripmarker but not one of the three defined forms
end
return true, value:gsub (stripmarker, rendering, 1);
end
--[[--------------------------< C O I N S _ C L E A N U P >----------------------------------------------------
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities.
2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content
when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible
characters table?
]]
local function coins_cleanup (value)
local replaced = true; -- default state to get the do loop running
while replaced do -- loop until all math stripmarkers replaced
replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation
end
value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message
value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content
value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">'(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s
value = value:gsub (' ', ' '); -- replace entity with plain space
value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space
if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script
value = value:gsub ('‍', ''); -- remove ‍ entities
value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen
end
value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space
return value;
end
--[[--------------------------< C O I N S >--------------------------------------------------------------------
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.
]]
local function COinS (data, class)
if 'table' ~= type (data) or nil == next (data) then
return '';
end
for k, v in pairs (data) do -- spin through all of the metadata parameter values
if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)
data[k] = coins_cleanup (v);
end
end
local ctx_ver = "Z39.88-2004";
-- treat table strictly as an array with only set values.
local OCinSoutput = setmetatable ({}, {
__newindex = function(self, key, value)
if is_set (value) then
rawset (self, #self+1, table.concat {key, '=', mw.uri.encode (remove_wiki_link (value))});
end
end
});
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn', 'journal', 'news', 'magazine'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or
('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) then -- set genre according to the type of citation template we are rendering
OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite ssrn
elseif 'conference' == class then
OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set)
elseif 'web' == class then
OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set)
else
OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles
end
OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only
if is_set (data.Map) then
OCinSoutput["rft.atitle"] = data.Map; -- for a map in a periodical
else
OCinSoutput["rft.atitle"] = make_coins_title (data.Title, data.ScriptTitle);
-- all other 'periodical' article titles
end
-- these used onlu for periodicals
OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall
OCinSoutput["rft.chron"] = data.Chron; -- free-form date components
OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books
OCinSoutput["rft.issue"] = data.Issue;
OCinSoutput["rft.pages"] = get_coins_pages (data.Pages); -- also used in book metadata
elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier
if 'report' == class or 'techreport' == class then -- cite report and cite techreport
OCinSoutput["rft.genre"] = "report";
elseif 'conference' == class then -- cite conference when Periodical not set
OCinSoutput["rft.genre"] = "conference";
elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then
if is_set (data.Chapter) or is_set (data.ScriptChapter) then
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.atitle"] = make_coins_title (data.Chapter, data.ScriptChapter);
-- book chapter, encyclopedia article, interview in a book, or map title
else
if 'map' == class or 'interview' == class then
OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview
else
OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia
end
end
else --{'AV media', 'AV media notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}
OCinSoutput["rft.genre"] = "unknown";
end
OCinSoutput["rft.btitle"] = make_coins_title (data.Title, data.ScriptTitle);
-- book only
OCinSoutput["rft.place"] = data.PublicationPlace; -- book only
OCinSoutput["rft.series"] = data.Series; -- book only
OCinSoutput["rft.pages"] = get_coins_pages (data.Pages); -- book, journal
OCinSoutput["rft.edition"] = data.Edition; -- book only
OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation
else -- cite thesis
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier
OCinSoutput["rft.title"] = make_coins_title (data.Title, data.ScriptTitle);
-- dissertation (also patent but that is not yet supported)
OCinSoutput["rft.degree"] = data.Degree; -- dissertation only
OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation
end
-- and now common parameters (as much as possible)
OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation
for k, v in pairs (data.ID_list) do -- what to do about these? For now assume that they are common to all?
if k == 'ISBN' then v = v:gsub ("[^-0-9X]", ""); end
local id = cfg.id_handlers[k].COinS;
if string.sub (id or "", 1, 4) == 'info' then -- for ids that are in the info:registry
OCinSoutput["rft_id"] = table.concat {id, "/", v};
elseif string.sub (id or "", 1, 3) == 'rft' then -- for isbn, issn, eissn, etc that have defined COinS keywords
OCinSoutput[id] = v;
elseif id then -- when cfg.id_handlers[k].COinS is not nil
OCinSoutput["rft_id"] = table.concat {cfg.id_handlers[k].prefix, v};-- others; provide a url
end
end
local last, first;
for k, v in ipairs (data.Authors) do
last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki strip markers, non-printing or invisible characers
if k == 1 then -- for the first author name only
if is_set (last) and is_set (first) then -- set these COinS values if |first= and |last= specify the first author name
OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation
OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name
end
else -- for all other authors
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat {last, ", ", first}; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation
end
end
end
OCinSoutput.rft_id = data.URL;
OCinSoutput.rfr_id = table.concat {"info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage};
OCinSoutput = setmetatable (OCinSoutput, nil);
-- sort with version string always first, and combine.
table.sort (OCinSoutput);
table.insert (OCinSoutput, 1, "ctx_ver=" .. ctx_ver); -- such as "Z39.88-2004"
return table.concat (OCinSoutput, "&");
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set; -- import functions from selected Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array;
strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup;
remove_wiki_link = links_page_ptr.remove_wiki_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
COinS = COinS,
set_selected_modules = set_selected_modules,
}
a6a4da2d79b0f571a56787451c79021e7a1b4cf1
Template:Cite web
10
173
348
2022-04-26T16:53:03Z
zhwp>Antigng
0
回退[[Special:Contributions/Antigng|Antigng]]([[User talk:Antigng|对话]])的编辑,改回[[Special:Contributions/范|范]]的最后一个版本
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#invoke:citation/CS1|citation
|CitationClass=web
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
3b7682ef53d882ae11de29b97be5a15ef317eee3
Template:Internal link helper/en
10
309
643
2022-05-03T13:12:16Z
zhwp>Xiplus
0
優化 [[Special:PermaLink/71452379#Template:Translink簡化VPT]]
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=en |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>
{{Documentation|Template:Internal link helper/doc}}
</noinclude>
8879dbc293b7701b98990406b06eb03f75ed837e
Template:Translink
10
307
639
2022-05-03T14:13:03Z
zhwp>Xiplus
0
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh |main |lang-code={{{1}}} |1={{#if:{{{3|}}}|{{{3}}}|{{{2}}}}} |2={{{2|}}} |d={{{4|}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation}}</noinclude>
5bdf50d43763a30c17c72549cf86b4548c13651a
Module:Ilh
828
310
645
2022-05-03T14:34:07Z
zhwp>Xiplus
0
修正display參數無效問題
Scribunto
text/plain
local ilh = {}
local getArgs
local yesno = require('Module:Yesno')
local lan = require('Module:Lan')
local langData = mw.loadData( 'Module:Ilh/data' )
--local frameArgs
local COMMON_TAIL='</span>'
local MODEL={
frame_head='<span class="ilh-all %s" data-orig-title="%s" data-lang-code="%s" data-lang-name="%s" data-foreign-title="%s">'
,frame_tail=COMMON_TAIL
,page_head='<span class="ilh-page">'
,page_tail=COMMON_TAIL
,comment_head='<span class="noprint ilh-comment">('
,comment_tail=')'..COMMON_TAIL
,lang_head='<span class="ilh-lang">'
,lang_tail=COMMON_TAIL
,colon='<span class="ilh-colon">:</span>'
,link_head='<span class="ilh-link">'
,link_body='-{[[:%s:%s|<span lang="%s" dir="auto">%s</span>]]}-'
,link_tail=COMMON_TAIL
}
local clazz_pageExist_framehead='ilh-blue'
local TRA_CAT='[[Category:有蓝链却未移除内部链接助手模板的页面]]'
function ilh.main(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame)
if langData[args['lang-code']] == nil then
args['lang'] = mw.language.fetchLanguageName( args['lang-code'], mw.getContentLanguage():getCode() )
elseif langData[args['lang-code']]['lang-hans'] and langData[args['lang-code']]['lang-hans'] then
args['lang'] = lan._main({['zh-hans']=langData[args['lang-code']]['lang-hans'], ['zh-hant']=langData[args['lang-code']]['lang-hant']}, frame)
elseif langData[args['lang-code']]['lang'] == nil then
args['lang'] = mw.language.fetchLanguageName( args['lang-code'], mw.getContentLanguage():getCode() )
else
args['lang'] = langData[args['lang-code']]['lang']
end
return ilh._ilh(args)
end
function ilh._ilh(args)
--frameArgs = getArgs(frame, {frameOnly=true})
local context={}
context["isMainPage"]=ilh.isMainPage()
context["localPage"]=args[1]
context["foreignPage"]=args[2] or args[1] --如果{{{2}}}不传入的话
context["displayName"]=args["d"] or args[1]
context["langCode"]=args["lang-code"]
context["lang"]=args["lang"]
context["nocat"]=yesno( args["nocat"] , false )
context["isExist"]= (args["$exist$"] and args["$exist$"]==1) or ilh.isExist(context["localPage"])
local curPage_obj=mw.title.getCurrentTitle()
context["isNoCatWithNamespace"]=curPage_obj:inNamespaces(2,828) --User,Module
--context["curPageNamespace"]=curPage_obj.namespace
return (context["isMainPage"] and ilh.onlyLink(context)) or ilh.functionLink(context)
end
function ilh.onlyLink(context)
return ( context["isExist"] and mw.ustring.format( '[[%s|%s]]', context["localPage"], context["displayName"] ) ) or context["displayName"]
end
function ilh.functionLink(context)
context["_localPage"]=mw.ustring.gsub(context["localPage"],'"','"')
context["_foreignPage"]=mw.ustring.gsub(context["foreignPage"],'"','"')
local need_cat=
(not context["nocat"])
and
(not context["isNoCatWithNamespace"])
--[[not (
context["curPageNamespace"]==2 --User
or context["curPageNamespace"]==828 --Module
)]]
--mw.log(context["nocat"])
--mw.log(context["curPageNamespace"])
--mw.log(need_cat)
local output_context={}
table.insert(output_context,
mw.ustring.format(MODEL.frame_head ,
(context["isExist"] and clazz_pageExist_framehead) or ''
,context["_localPage"]
,context["langCode"]
,context["lang"]
,context["_foreignPage"]
)
)
table.insert(output_context,MODEL.page_head)
table.insert(output_context,
mw.ustring.format('[[:%s|%s]]' ,
context["localPage"],context["displayName"]
)
)
table.insert(output_context,MODEL.page_tail)
if context["isExist"] then
if need_cat then
table.insert(output_context,TRA_CAT)
end
else
table.insert(output_context,MODEL.comment_head)
table.insert(output_context,MODEL.lang_head)
table.insert(output_context,context["lang"])
table.insert(output_context,MODEL.lang_tail)
table.insert(output_context,MODEL.colon)
table.insert(output_context,MODEL.link_head)
table.insert(output_context,
mw.ustring.format(MODEL.link_body,
context["langCode"]
,(context["foreignPage"] or context["localPage"])
,context["langCode"]
,(context["foreignPage"] or context["localPage"])
)
)
table.insert(output_context,MODEL.link_tail)
table.insert(output_context,MODEL.comment_tail)
end
table.insert(output_context,MODEL.frame_tail)
return table.concat(output_context,"")
end
--以下需要更高效的实现
--确定主页
--使用mw信息获得主页名
--使用language库获得本站默认语言代码(zh)来确定信息的对应语言,获得全主页名
---因为其他zh分语言只有名,没有命名空间,可以识别出来,但麻烦
--然后判断当前页和主页是否一致
---计划做重定向判断,但没需要
function ilh.isMainPage()
local mainpage_msgobj=mw.message.new('Mainpage')
mainpage_msgobj=mainpage_msgobj:inLanguage(mw.getContentLanguage():getCode())
local mainPage_obj=mw.title.makeTitle(0,mainpage_msgobj:plain())
local curpage_obj=mw.title.getCurrentTitle()
--local curpage_redirectFrom_obj=curpage_obj.redirectTarget
--[[if curpage_redirectFrom_obj ~=false then
curpage_obj=curpage_redirectFrom_obj
end]]
return mw.title.equals(mainPage_obj,curpage_obj) --and curpage_obj.namespace==4
end
--确定页面存在
---exists是高开销方法,需要更高效的实现
--带保护的包装方法
--由于exists和解析器函数ifexist都是高开销方法
--而ifexist达到限制时默认返回结果为false的操作
--而exists会直接抛出错误而中断执行
--所以将相应调用包裹,压制exists的抛错,按照ifexist的理念,返回false
--正常情况下则一切正常
function ilh.isExist(pageName)
local execStatus,result=pcall(ilh._isExist,pageName)
if execStatus then
return result
else
return false
end
end
--真实方法
function ilh._isExist(pageName)
local localPage_obj=mw.title.makeTitle(0,pageName)
return localPage_obj.exists
end
--end
return ilh
f7db743d76a68ad6582c917defa3d289efa4ce88
Template:Internal link helper/ja
10
314
653
2022-05-03T14:36:42Z
zhwp>Xiplus
0
優化 [[Special:PermaLink/71452379#Template:Translink簡化|VPT]]
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=ja |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation|Template:Internal link helper/doc}}</noinclude>
878849200bafc1f6e2da1f4f33180f8c1c027bb7
Template:Internal link helper/ru
10
312
649
2022-05-03T14:37:14Z
zhwp>Xiplus
0
優化 [[Special:PermaLink/71452379#Template:Translink簡化|VPT]]
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=ru |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation|Template:Internal link helper/doc}}</noinclude>
1161f8b9d160907c3a14c7a7e87642d707fda5d2
Module:CGroup/core
828
128
252
2022-05-09T00:05:12Z
zhwp>Xiplus-abot
0
已更改“[[Module:CGroup/core]]”的保护设置:高風險模板:100059引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local p = {}
function p.Item(o, r)
-- See [[那艺娜维基:字詞轉換處理/公共轉換組]]
-- o: 原文。若無此屬性,應使用nil而非空字串('')。
-- r: 用於全文轉換的規則,必填。
return { type = 'item', original = o, rule = r };
end
return p
97c445f7e3f780f771b528f0f42a6367ba48b2de
354
252
2022-05-09T00:05:12Z
zhwp>Xiplus-abot
0
已更改“[[Module:CGroup/core]]”的保护设置:高風險模板:100059引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local p = {}
function p.Item(o, r)
-- See [[Wikipedia:字詞轉換處理/公共轉換組]]
-- o: 原文。若無此屬性,應使用nil而非空字串('')。
-- r: 用於全文轉換的規則,必填。
return { type = 'item', original = o, rule = r };
end
return p
e67f5d830f43e1db2ea92ad98f93c0000b4d2423
Template:改进使用说明
10
276
576
2022-05-09T09:15:12Z
zhwp>YFdyh000
0
修正笔误
wikitext
text/x-wiki
{{SAFESUBST:<noinclude />#invoke:Unsubst||date=__DATE__ |$B={{Ombox
| type = content
| name = 改进使用说明
| class = ambox-Refimprove
| image = [[File:Edit-copy green with red question mark.svg|50x40px|alt=]]
| text = 此{{#switch:{{NAMESPACE}}|Module=模块|#default=模板}}的[[Wikipedia:模板文件頁模式|文档]]'''不存在、不全面或不能详细描述其功能及/或其代码中的[[Help:模板|参数]]。'''请帮助[{{fullurl:{{FULLPAGENAME}}{{#ifexist:{{FULLPAGENAME}}/doc|/doc}}|action=edit}} 扩充并改进其文档。]{{#if:{{{talk|{{{1|}}}}}} |请参阅[[{{TALKPAGENAME}}|其讨论页]]了解详情。|}} {{#if:{{{date|{{{2|}}}}}} |{{smaller|''({{{date}}})''}}}}
}}<includeonly>{{#ifeq:{{{中文}}}|是|[[Category:可能需要翻譯使用說明的模板|{{PAGENAME}}]]|{{Dated maintenance category|||缺少或文档内容不准确的模板}}}}</includeonly>}}<noinclude>
{{Documentation}}
</noinclude>
af7b64a3cb3fe193b116044d7e46261db0179e7d
Template:缺乏使用說明
10
277
578
2022-05-09T09:16:10Z
zhwp>YFdyh000
0
合并
wikitext
text/x-wiki
#REDIRECT [[Template:改进使用说明]]
54637eee98f16dd913f0ee4edb6d5db001566d19
Template:Bot/doc
10
256
529
2022-05-11T08:41:03Z
zhwp>Raymon090
0
wikitext
text/x-wiki
<noinclude>{{Documentation subpage}}</noinclude>
{{Bot use warning|bots=[[User:Cewbot]]。}}
<!-- 在本行下編輯模板說明 -->
== 參數及使用方法 ==
; 1 : 第一個參數為機械人操作者。<br />The first unnamed parameter specifies the operator of the bot.
; 2, 3 : 如有需要,第二及第三個參數為其他機械人共同操作者。<br />The second and third unnamed parameters can be used to specify co-operators of the bot, if required.
; site : 操作者如無本地帳戶,則可輸入兩個字母語言代碼。<br />The two letter code for those operators that do not have an account on the English language Wikipedia (though having a local account is strongly recommended).
; status : ''active''(在用而且已得到批准)、 ''inactive''(得到批准但不在用)、''trial''(測試中)或''unapproved''(未批准或許可已撤銷)<br />''active'' (and approved), ''inactive'' (but approved), ''trial'' or ''unapproved''
; awb : ''yes'' (如有使用[[那艺娜维基:AutoWikiBrowser|AWB]])或留空(如果並非使用AWB)<br />''yes'' (if this bot uses [[那艺娜维基:AutoWikiBrowser|AWB]]), or omit (if it doesn't).
; codebase: 機械人所使用程序語言(例如︰[[mw:Pywikibot|Pywikibot]]、[[m:perlwikipedia|perlWikipedia]]……)<br />The name of the code (programming or scripting language) used to create the bot (e.g., [[mw:Pywikibot|Pywikibot]], [[m:perlwikipedia|perlWikipedia]], ...)
; brfa : '''選填'''︰如有,就會更改內鏈連接,否則就會連接到<nowiki>{{BASEPAGENAME}}</nowiki>。<br />''Optional'' if specified, overrides the name of the request for approval. If not specified, defaults to <nowiki>{{BASEPAGENAME}}</nowiki>
; by : '''選填'''︰如有就會蓋過頭三個參數,即1,2及3,改為顯示此參數所帶內容。<br />''Optional'' if specified, overrides the usual display of the operator's username in the first line generated from the three unnamed parameters.
; approvalneeded : 如果上面'''status'''標記為「active/approved」,而且在此參數輸入<kbd>yes</kbd>,則模板會標示該機械人所執行事項為毋須事先取得批准。<br />If '''status''' indicated ''active/approved'', setting <kbd>yes</kbd> will make the template indicate that the bot is running tasks for which no approval is needed.
; overridebrfa : 如果機械人曾經遞交過幾項申請、得到過幾次批准或有幾項工作,而預設BRFA連結未能夠顯示所有已批准申請或工作,則可在此參數輸入其他維基百科頁面連結。此參數會蓋過'''brfa'''。<br />If the bot has multiple requests or approval, or multiple tasks, and the default BRFA link cannot link to a page that contains all the bot's approved requests or tasks, this field allows inputting a link to any Wikipedia page. Specifying this field overrides '''brfa'''.
; more : 其他額外資訊,通常不用,因為{{para|status}}、{{para|brfa}}及{{para|approvalneeded}}已包含大部分資訊。<br />Any ''additional'' information to specify in the mbox. Usually not needed, since {{para|status}}, {{para|brfa}}, and {{para|approvalneeded}} covers most cases.
; alt : '''選填'''︰圖檔替代文字。<br />Optional alternate text for the image.
== 範例 ==
<!-- for the documentation don't subst the result -->
{| class="wikitable mbox-inside"
|-
! Code
! Result
|-
| <code>{{tlp|{{BASEPAGENAME}}|Example}}</code>
|
{{{{BASEPAGENAME}}|Example|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|awb=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|awb=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|codebase=[[m:perlwikipedia|perlWikipedia]]</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en |codebase=[[m:perlwikipedia|perlWikipedia]]|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=active</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=trial</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=trial|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=inactive</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=inactive|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=unapproved</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=unapproved|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|status=active|globalbot=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|globalbot=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|image=Crystal Clear question bot.svg</nowiki><br /><nowiki>|more=此機器人正在測試中。</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|image=Crystal Clear question bot.svg|more=此機器人正在測試中。|nocat=}}
|}
== 參見 ==
* {{tl|User bot owner}}
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[那艺娜维基:Wikidata]]) -->
[[Category:維基百科機器人模板|{{PAGENAME}}]]
}}</includeonly>
6629e6cd5ddae698eb3a64247873c22620e7bb32
Template:Age
10
226
471
2022-05-15T00:05:22Z
zhwp>Xiplus-abot
0
已更改“[[Template:Age]]”的保护设置:高風險模板:100007引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
{{#invoke:age|age_generic|template=age_full_years}}<noinclude>{{documentation}}</noinclude>
0bb21e2a735de3813c6688d5c260c5596c9cee37
Template:出生、逝世及日期模板
10
241
501
2022-05-16T16:10:42Z
zhwp>Tjmj
0
參考EN維基2022-02-18T19:46:25版本
wikitext
text/x-wiki
{{Navbox with collapsible groups
| name = 出生、逝世及日期模板
| state = {{{state|expanded}}}
| title = 出生、逝世及日期模板
| selected = {{{selected|{{{expanded|{{{1|}}}}}}}}}
| listclass = hlist <!-- can't see why tracking=no doesn't work, but this does -->
| tracking = <includeonly>no</includeonly>
<!----------------------------------------------------------------------------->
| abbr1 = BDA
| section1 = 出生,逝世,年龄
| content1 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|BirthDeathAge}} | Combines functions of <nowiki>{{Birth date}}, {{Birth-date}}, {{Birth date and age}}, {{Birth year and age}}, {{Death date}}, {{Death-date}}, {{Death date and age}}, and {{Death year and age}}.</nowiki>
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Birth date}} | To display a birth date and related hidden metadata.
| {{Tl|Birth-date}} |
| {{Tl|Birth date and age}} | {{Tlf|Birth date}} with suffix "(age ''N'')".
| {{Tl|Birth date and age2}} | {{Tlf|Birth date and age}} plus age as of a specified date.
| {{Tl|Birth-date and age}} | As {{Tlf|Birth date and age}} but accepts dates in text form ("15 June 1950", "June 15, 1950", "June 1950", etc).
| {{Tl|Birth year and age}} | Year of birth and approximate age.
| {{Tl|Birth based on age as of date}} | To display approximate birth year and current age given a particular date (e.g. when a dated reference mentions the age of a person).
| {{Tl|Birth date based on age at death}} | To display approximate birth year based on age at death.
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Death date}} | To display a death date and related hidden metadata.
| {{Tl|Death-date}} |
| {{Tl|Death date and age}} | {{Tlf|Death date}} with suffix "(aged ''N'')". Also called with {{tlf|event date and age}}
| {{Tl|Death-date and age}} | As {{Tlf|Death date and age}} but accepts dates in text form ("15 June 1950", "June 15, 1950", "June 1950", etc).
| {{Tl|Death date and given age}} | To display a death date and specified age.
| {{Tl|Death year and age}} | To display a year of and approximate age at death.
}}
<!----------------------------------------------------------------------------->
| abbr2 = age
| section2 = 只有年龄
| content2 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:20em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Age in years, months, weeks and days}} | Number of complete years, months, weeks and days between two dates.
| {{Tl|Age in years, months and days}} | Number of complete years, months and days between two dates.
| {{Tl|Age in years and months}} | Number of complete years and remaining months between two dates.
| {{Tl|Age in years and days}} | Number of complete years and remaining days between two dates.
| {{Tl|Age in years and days nts}} | {{Tlf|Age in years and days}} with output formatted for use in [[Help:可排序表格|number sortable tables]].
| {{Tl|Age in decimal years}} | Number of years between two dates, rounded to the specified number of decimal places.
| {{Tl|Age in years}} | Number of years between two dates.
| {{Tl|Age in years nts}} | {{Tlf|Age in years}} with output formatted for use in sortable tables.
| {{Tl|Age in months}} | Number of months between two dates.
| {{Tl|Age in weeks and days}} | Number of weeks and days between two dates.
| {{Tl|Age in weeks}} | Number of weeks between two dates.
| {{Tl|Age in days}} | Age in days between two dates.
| {{Tl|Age in days nts}} | {{Tlf|Age in days}} with output formatted for use in sortable tables.
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:20em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Age}} | Age based on number of complete years between two dates.
| {{Tl|Age nts}} | {{Tlf|Age}} with output formatted for use in [[Help:可排序表格]].
| {{Tl|Age as of date}} | Current age (in years) from a known age at a specified date.
| {{Tl|Age for infant}} | Current age for infant: months and days up to one year, years and months up to three years, and years beyond age 3.
}}
<!----------------------------------------------------------------------------->
| abbr3 = dates
| section3 = 开始{{\}}结束时间
| content3 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Start date}} / {{Tl|End date}} |
| {{Tl|Start-date}} / {{Tl|End-date}} |
| {{Tl|Start date and age}} |
| {{Tl|End date and age}} |
}}
<!----------------------------------------------------------------------------->
| abbr4 = misc
| section4 = 杂项
| content4 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|OldStyleDate}} | Dates in [[儒略曆|Julian calendar]].
| {{Tl|OldStyleDateDY}} | As {{Tlf|OldStyleDate}} but used when Julian / [[格里曆|Gregorian date]]s fall in different years.
| {{Tl|OldStyleDateNY}} | As {{Tlf|OldStyleDate}} but without the year.
| {{Tl|Unidentified for}} |
| {{Tl|Missing for}} |
}}
<!----------------------------------------------------------------------------->
| belowclass = hlist
| belowstyle = font-weight:bold;
| below =
<!-- * [[Wikipedia:Age calculation templates|About age calculation templates]] -->
* 參見:[[:Category:日期计算模板|日期计算模板]]
}}<!--
--><noinclude>{{Documentation}}</noinclude>
76e9db694a82f0ba3efb5fa5f6116b50d3020592
Template:Bot
10
247
511
2022-05-19T14:48:48Z
zhwp>Xiplus
0
分類細分
wikitext
text/x-wiki
{{ombox
|image = [[File:{{{image|{{#switch: {{lc:{{{status}}}}}
|active
|approved = Crystal Clear accepted bot.png
|trial = Crystal Clear question bot.svg
|inactive = Crystal Clear inactive bot2.png
|unapproved = Crystal Clear denied bot.png
|#default = Crystal Clear action run.png
}}}}}|75px|{{{caption|This is a bot account.}}}|alt={{{alt|}}}]]
|text = '''此為[[那艺娜维基:Bot policy|機械人帳號]]{{#if:{{{codebase|}}}
|,使用{{{codebase}}}
|{{#ifeq: {{lc:{{{awb}}}}}|yes
|,使用[[WP:AWB|自動維基瀏覽器]]
}}}},操作者為{{{by|[[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User:{{Trim|{{{1}}}}}|{{Trim|{{{1}}}}}]]([[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User talk:{{{talklink|{{Trim|{{{1}}}}}}}}|討論]]){{#if:{{Trim|{{{2|}}}}}
|{{#if:{{Trim|{{{3|}}}}}
|、
|及
}}[[:zh:User:{{Trim|{{{2}}}}}|{{Trim|{{{2}}}}}]]([[:zh:User talk:{{{talklink|{{Trim|{{{2}}}}}}}}|討論]])
}}{{#if:{{Trim|{{{3|}}}}}
|及[[:zh:User:{{Trim|{{{3}}}}}|{{Trim|{{{3}}}}}]]([[:en:User talk:{{{talklink|{{Trim|{{{3}}}}}}}}|討論]])
}}}}},'''屬[[WP:SOCK#LEGIT|合規附屬帳戶]],以半自動或全自動方式協助用戶處理繁瑣而重複的工作。{{#switch: {{lc:{{{status}}}}}
|active
|approved = {{#if:{{{globalbot|}}}
|此為[{{fullurl:Special:GlobalUsers/Global_bot|limit=1&username={{urlencode:{{{username|{{BASEPAGENAME}}}}}}}}} 全域機械人],主要依據[[:meta:Bot_policy#Global_bots|元維基機械人方針]]處理跨語言連結或整理雙重重定向,現時在用。{{#if:{{{overridebrfa|}}}|另外,此帳戶亦會處理其他本地事務或者得到本地許可,詳請[[{{{overridebrfa}}}|見此]]。|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|另外,此帳戶得到本地許可,詳情[[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|見此]]。|}}}}
|{{#ifeq:{{{approvalneeded|}}}|no
| 此機械人在用,而所處理事務毋須事先取得[[WP:BRFA|許可]]。
| 此機械人已得到許可,亦正在運作中。{{#if:{{{overridebrfa|}}}|[[WP:BRFA|申請存檔]][[{{{overridebrfa}}}|見此]]|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|[[WP:BRFA|申請存檔]][[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|見此]]|{{{nocat|[[Category:無指明申請許可而在用維基百科機械人]]}}}}}}}
}}
}}{{{nocat|[[Category:在用維基百科機械人]]}}}
|inactive = {{#ifeq:{{{approvalneeded|}}}|no
| 此機械人現時不在用,而之前所負責事務毋須事先得到許可。
| 此機械人現時不在用,然而仍保有{{#if:{{{globalbot|}}}|全域|}}社群[[{{#if:{{{overridebrfa|}}}|{{{overridebrfa}}}|那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}}}|許可]]。{{{nocat|[[Category:不在用維基百科機械人]]}}}
}}
|trial = 此機械人獲得[[那艺娜维基:機械人審核小組|機械人審核小組]]批准有限度試行。{{{nocat|[[Category:未批准維基百科機械人]]}}}
|unapproved = 此機械人並未獲得社群批准運作,或其操作許可已被撤銷,是故不應進行大規模操作,亦請勿在缺乏操作者監察下運作,操作者及机器人用戶空間除外。{{{nocat|[[Category:未批准維基百科機械人]]}}}
|#default = {{{nocat|<includeonly>[[Category:未知狀態維基百科機械人]]</includeonly>}}}
}}{{{more|}}}<br/><small>{{#ifeq:{{lc:{{{awb}}}}}|yes
|如要使此機械人停止運作直至操作者重啟,請編輯[[User talk:{{PAGENAME}}|機械人討論頁]]。如果討論頁為重定向,請直接編輯重定向本身,而非所指向的頁面。
}} <span class="sysop-show">'''管理員︰若然此機械人{{#ifeq: {{lc:{{{status}}}}}|unapproved
|進行大規模操作或相信在缺乏監察下運作,而且所編輯區域並非操作者或機械人用戶名字空間
|{{#ifeq:{{lc:{{{awb}}}}}|yes
|在收到提醒或警告訊息後繼續作出有問題編輯
|失靈或作出有問題編輯
}}
}},請[{{fullurl:Special:Block|wpTarget={{PAGENAMEE}}&wpExpiry=indefinite&wpHardBlock=1&wpAutoBlock=0&wpCreateAccount=0&wpReason=機器人發生故障並必須緊急停止}} 施予封禁]{{#ifeq:{{lc:{{{awb}}}}}|yes
|或者移除其[[那艺娜维基:AutoWikiBrowser/CheckPage|自動維基瀏覽器使用權]]
}}。'''</span></small>
|imageright={{#ifeq: {{lc:{{{awb}}}}}|yes
|[[File:AWB_logo_draft.png|75px]]{{{nocat|[[Category:自动维基浏览器使用者]]}}}
}}<includeonly>{{{nocat|[[Category:所有維基百科機器人]]{{#if:{{{globalbot|}}}|[[Category:全域維基百科機械人]][[Category:跨語言連接機械人]]|}}}}}</includeonly>
}}<noinclude>
{{documentation}}
</noinclude>
7c7dede67ac480f0382c74e9c6950f0d2f9ec71f
Module:Citation/CS1
828
175
356
2022-06-05T14:33:51Z
zhwp>Antigng
0
修复显而易见的bug(无需共识)
Scribunto
text/plain
--[[--------------------------< I M P O R T E D _ F U N C T I O N S _ A N D _ V A R I B L E S >-----------------
]]
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
local dates, year_date_check; -- functions in Module:Citation/CS1/Date_validation
local add_maint_cat, append_error, make_error_tail, reset_error, set_error, select_one, throw_error;
-- error-related functions in Module:Citation/CS1/Error
local first_set, hyphen_to_dash, is_set, in_array, substitute; -- simple functions in Module:Citation/CS1/Utilities
local has_invisible_chars, kern_quotes, pend_separator, safe_join, wrap_style, wrap_msg;
-- style-related functions in Module:Citation/CS1/Utilities
local check_for_external_link, make_external_link, make_internal_link; -- link-related functions in Module:Citation/CS1/Links
local extract_ids, build_id_list, is_embargoed, extract_id_access_levels; -- functions in Module:Citation/CS1/Identifiers
local get_people, format_people; -- functions in Module:Citation/CS1/People
local COinS; -- functions in Module:Citation/CS1/COinS
local script_concatenate, language_parameter; -- functions in Module:Citation/CS1/Language
local function load_modules (module_path, module_suffix)
cfg = mw.loadData (module_path .. 'Configuration' .. module_suffix);
whitelist = mw.loadData (module_path .. 'Whitelist' .. module_suffix);
local validation = require (module_path .. 'Date_validation' .. module_suffix);
local identifiers = require (module_path .. 'Identifiers' .. module_suffix);
local utilities = require (module_path .. 'Utilities' .. module_suffix);
local people = require (module_path .. 'People' .. module_suffix);
local links = require (module_path .. 'Links' .. module_suffix);
local errors = require (module_path .. 'Error' .. module_suffix);
local coins = require (module_path .. 'COinS' .. module_suffix);
local languages = require (module_path .. 'Language' .. module_suffix);
utilities.set_selected_modules (cfg);
links.set_selected_modules (utilities, errors);
errors.set_selected_modules (cfg, utilities, links);
identifiers.set_selected_modules (cfg, utilities, errors, links, validation);
people.set_selected_modules (cfg, utilities, errors, links);
coins.set_selected_modules (cfg, utilities, links);
languages.set_selected_modules (utilities, errors);
dates = validation.dates; -- imported functions
year_date_check = validation.year_date_check;
first_set = utilities.first_set;
hyphen_to_dash = utilities.hyphen_to_dash;
is_set = utilities.is_set;
in_array = utilities.in_array;
substitute = utilities.substitute;
has_invisible_chars = utilities.has_invisible_chars;
kern_quotes = utilities.kern_quotes;
pend_separator = utilities.pend_separator;
safe_join = utilities.safe_join;
wrap_style = utilities.wrap_style;
wrap_msg = utilities.wrap_msg;
make_external_link = links.make_external_link;
make_internal_link = links.make_internal_link;
check_for_external_link = links.check_for_external_link;
add_maint_cat = errors.add_maint_cat;
append_error = errors.append_error;
make_error_tail = errors.make_error_tail;
reset_error = errors.reset_error;
set_error = errors.set_error;
select_one = errors.select_one;
throw_error = errors.throw_error;
extract_ids = identifiers.extract_ids;
build_id_list = identifiers.build_id_list;
is_embargoed = identifiers.is_embargoed;
extract_id_access_levels = identifiers.extract_id_access_levels;
get_people = people.get_people;
format_people = people.format_people;
COinS = coins.COinS;
script_concatenate = languages.script_concatenate;
language_parameter = languages.language_parameter;
end
--[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the
offending parameter name to the error message.
]]
local function deprecated_parameter (name)
append_error ('deprecated_params', {name});
end
--[[--------------------------< D I S C A R D _ P A R A M E T E R >--------------------------------------------
]]
local function discard_parameter (name, label, new_value)
if is_set (name) then
append_error ('parameter_discarded', label);
end
return new_value;
end
--[[--------------------------< S A N I T I Z E D _ P A R A M E T E R _ V A L U E >------------------------
This function is used to validate a parameter's assigned value for those parameters that have only a limited number
of allowable values (e.g. yes, y, true, no, etc). If the parameter value is empty or is in the list of allowed values,
the function returns the value; else, it emits an error message and returns the default value.
]]
local function sanitized_parameter_value (value, name, key, default)
if not is_set (value) then
return value; -- an empty parameter is ok
elseif in_array (value:lower(), cfg.keywords[key]) then
return value;
else
append_error ('invalid_param_val', {name, value}); -- not an allowed value so add error message
return default;
end
end
--[[--------------------------< E X T R A _ T E X T _ I N _ P A R A M E T E R _ C H E C K >------------------------------
]]
local function extra_text_in_parameter_check (value, type)
local good_patterns = cfg.extra_text_pattern[type]['good'];
local bad_patterns = cfg.extra_text_pattern[type]['bad'];
for _, pattern in pairs (good_patterns) do
if value:match (pattern) then
return;
end
end
for _, pattern in pairs (bad_patterns) do
if value:match (pattern) then
add_maint_cat ('extra_text', type);
return;
end
end
end
--[[--------------------------< V A L I D A T E _ D A T E >-------------------------------------------------------
Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where
we get the date used in the metadata.
Date validation supporting code is in Module:Citation/CS1/Date_validation
]]
local function validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, origin)
local error_message = '';
-- AirDate has been promoted to Date so not necessary to check it
anchor_year, error_message = dates ({['access-date']=AccessDate, ['archive-date']=ArchiveDate, ['date']=Date, ['doi-broken-date']=DoiBroken,
['embargo']=Embargo, ['lay-date']=LayDate, ['publication-date']=PublicationDate, ['year']=Year}, COinS_date);
if is_set (Year) then
if is_set (Date) then -- both |date= and |year= not normally needed;
local mismatch = year_date_check (Year, Date)
if 0 == mismatch then -- |year= does not match a year-value in |date=
append_error ('date_year_mismatch', {origin});
elseif 1 == mismatch then -- |year= matches year-value in |date=
add_maint_cat ('date_year');
end
end
anchor_year = Year; -- Year first for legacy citations and for YMD dates that require disambiguation
end
if is_set (error_message) then
append_error ('bad_date', {error_message}); -- add this error message
end
return anchor_year;
end
--[[--------------------------< D I S C A R D _ C H A P T E R >-------------------------------------------------------
仅为保持兼容性而设置。理论上可以直接调用discard_parameter()丢弃相关参数。
]]
local function discard_chapter (args)
local chap_param;
if is_set (args['Chapter']) then -- get a parameter name from one of these chapter related meta-parameters
chap_param = args:ORIGIN ('Chapter');
elseif is_set (args['TransChapter']) then
chap_param = args:ORIGIN ('TransChapter');
elseif is_set (args['ChapterURL']) then
chap_param = args:ORIGIN ('ChapterURL');
elseif is_set (args['ScriptChapter']) then
chap_param = args:ORIGIN ('ScriptChapter')
elseif is_set (args['ChapterFormat']) then
chap_param = args:ORIGIN ('ChapterFormat')
elseif is_set (args['ChapterUrlAccess']) then
chap_param = args:ORIGIN ('ChapterUrlAccess')
end
if is_set (chap_param) then -- if we found one
append_error ('chapter_ignored', {chap_param}); -- add error message
end
end
--[[--------------------------< C R E A T E _ U R L _ O B J E C T >------------------------------------------
]]
local function create_url_object (url, source, fmt, fmt_source, access, access_source)
return {
['url'] = is_set (url) and url or '',
['origin'] = is_set (source) and source or '',
['access'] = is_set (access) and sanitized_parameter_value (access, access_source, 'url-access', '') or '',
['access-origin'] = is_set (access_source) and access_source or '',
['format'] = is_set (fmt) and fmt or '',
['format-origin'] = is_set (fmt_source) and fmt_source or '',
['access-text'] = ''
}
end
--[[--------------------------< S E T _ T I T L E T Y P E >----------------------------------------------------
This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults.
Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none).
]]
local function set_titletype (cite_class, title_type)
if is_set (title_type) then
if 'none' == title_type then
title_type = ''; -- if |type=none then type parameter not displayed
end
return title_type; -- if |type= has been set to any other value use that value
end
return cfg.title_types[cite_class] or ''; -- set template's default title type; else empty string for concatenation
end
--[[--------------------------< S E T _ N O _ T R A C K I N G _ C A T S >-----------------------------------------
check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories
]]
local function set_no_tracking_cats (no_tracking, no_tracking_source, this_page)
local no_tracking_cats = sanitized_parameter_value (no_tracking, no_tracking_source, 'yes_true_y', nil);
if not is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page
if in_array (this_page.nsText, cfg.uncategorized_namespaces) then
return true; -- set no_tracking_cats
end
for _,v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns
if this_page.text:match (v) then -- test page name against each pattern
return true; -- set no_tracking_cats; bail out if one is found
end
end
return false;
else
return true;
end
end
--[[--------------------------< S E T _ C S 1 _ S T Y L E >----------------------------------------------------
Set style settings for CS1 citation templates. Returns separator and postscript settings
]]
local function set_cs1_style (ps)
if not is_set (ps) then -- unless explicitely set to something
ps = '.'; -- terminate the rendered citation with a period
end
return '.', ps; -- separator is a full stop
end
--[[--------------------------< S E T _ C S 2 _ S T Y L E >----------------------------------------------------
Set style settings for CS2 citation templates. Returns separator, postscript, ref settings
]]
local function set_cs2_style (ps, ref)
if not is_set (ps) then -- if |postscript= has not been set, set cs2 default
ps = ''; -- make sure it isn't nil
end
if not is_set (ref) then -- if |ref= is not set
ref = 'harv'; -- set default |ref=harv
end
return ',', ps, ref; -- separator is a comma
end
--[[--------------------------< G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S >----------------------
When |mode= is not set or when its value is invalid, use config.CitationClass and parameter values to establish
rendered style.
]]
local function get_settings_from_cite_class (ps, ref, cite_class)
local sep;
if (cite_class == 'citation') then -- for citation templates (CS2)
sep, ps, ref = set_cs2_style (ps, ref);
else -- not a citation template so CS1
sep, ps = set_cs1_style (ps);
end
return sep, ps, ref -- return them all
end
--[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------
Establish basic style settings to be used when rendering the citation. Uses |mode= if set and valid or uses
config.CitationClass from the template's #invoke: to establish style.
]]
local function set_style (mode, mode_source, ps, ref, quote, cite_class)
local sep;
mode = sanitized_parameter_value (mode, mode_source, 'mode', ''):lower();
if 'cs2' == mode then -- if this template is to be rendered in CS2 (citation) style
sep, ps, ref = set_cs2_style (ps, ref);
elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style
sep, ps = set_cs1_style (ps);
else -- anything but cs1 or cs2
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass
end
if 'none' == ps:lower() or is_set (quote) then -- if assigned value is 'none' then set it to empty string
ps = ''; -- also cs1|2 does not supply terminal punctuation when |quote= is set
end
return sep, ps, ref
end
--[[--------------------------< S W A P _ U R L S >--------------------------------------------------------------
]]
local function swap_urls (url_object, chapter_url_object, archive_url_object, dead_url)
local original_url_object = create_url_object ();
local is_dead = in_array (dead_url, cfg.keywords['deadurl-live']); -- used later when assembling archived text
if is_set (archive_url_object['url']) then
if is_set (url_object['url']) then
original_url_object = url_object;
if not is_dead then
url_object = archive_url_object;
end
elseif is_set (chapter_url_object['url']) then -- URL not set so if chapter-url is set apply archive url to it
original_url_object = chapter_url_object;
if not is_dead then
chapter_url_object = archive_url_object;
end
end
end
return original_url_object, url_object, chapter_url_object;
end
--[[--------------------------< F O R M A T _ U R L _ A C C E S S _ T E X T >---------------------------------------
从x-url-access系列参数生成相应的图标;兼容既有registration, subscription参数,优先级x-url-access > subscription > registration。
]]
local function format_url_access_text (url_object, subscription_required, registration_required)
local access_text = '';
local redundant = false;
local access = url_object['access'];
local reg = false;
local sub = false;
if is_set (access) then
if (access == 'limited') then
access_text = cfg.presentation['limited']; -- 有限度免费访问
elseif (access == 'registration') then
access_text = cfg.presentation['registration']; -- 需要免费注册
reg = true;
elseif (access == 'subscription') then
access_text = cfg.presentation['subscription']; -- 需要付费订阅
sub = true;
else
access_text = '';
end
if is_set (subscription_required) or is_set (registration_required) then
redundant = true;
end
else
if is_set (subscription_required) then
access_text = cfg.presentation['subscription']; -- 需要免费注册
sub = true;
if is_set (registration_required) then
redundant = true;
end
elseif is_set (registration_required) then
access_text = cfg.presentation['registration']; -- 需要付费订阅
reg = true
else
access_text = '';
end
end
if is_set (url_object ['url']) then
url_object['access-text'] = access_text;
if sub then
add_maint_cat ('subscription');
elseif reg then
add_maint_cat ('registration');
end
else
-- 预留报错
end
return redundant;
end
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >----------------------------------------
returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume
or formatted issue, or an empty string if neither are set.
]]
local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower)
if not is_set (volume) and not is_set (issue) then
return '';
end
if 'magazine' == cite_class or (cite_class =='map' and 'magazine' == origin) then
if is_set (volume) and is_set (issue) then
return wrap_msg ('vol-no', {sepc, volume, issue}, lower);
elseif is_set (volume) then
return wrap_msg ('vol', {sepc, volume}, lower);
else
return wrap_msg ('issue', {sepc, issue}, lower);
end
end
local vol = '';
if is_set (volume) then
if (6 < mw.ustring.len (volume)) then
vol = wrap_msg ('j-vol', {sepc, volume}, lower);
else
vol = wrap_style ('vol-bold', hyphen_to_dash (volume));
end
end
if is_set (issue) then
return vol .. wrap_msg ('j-issue', issue, lower);
end
return vol;
end
--[[-------------------------< F O R M A T _ I N S O U R C E _ L O C A T I O N >----------------------------------
Build insource_location meta-parameter from |page(s)= , |sheet(s)= , |at= and other relevant parameters.
]]
local function format_insource_location (page, pages, sheet, sheets, at, minutes, time, time_caption, section, sections, inset, cite_class, origin, sepc, nopp, lower)
local text = '';
if is_set (sheet) then
if 'journal' == origin then
text = wrap_msg ('j-sheet', sheet, lower);
else
text = wrap_msg ('sheet', {sepc, sheet}, lower);
end
elseif is_set (sheets) then
if 'journal' == origin then
text = wrap_msg ('j-sheets', sheets, lower);
else
text = wrap_msg ('sheets', {sepc, sheets}, lower);
end
end
local is_journal = 'journal' == cite_class or (cite_class == 'map' and 'journal' == origin);
if is_set (page) then
if is_journal then
text = wrap_msg ('j-page(s)', page, lower);
elseif not is_set (nopp) then
text = wrap_msg ('p-prefix', {sepc, page}, lower);
else
text = wrap_msg ('nopp', {sepc, page}, lower);
end
elseif is_set (pages) then
if is_journal then
text = wrap_msg ('j-page(s)', pages, lower);
elseif tonumber (pages) ~= nil and not is_set (nopp) then -- if pages is only digits, assume a single page number
text = wrap_msg ('p-prefix', {sepc, pages}, lower);
elseif not is_set (nopp) then
text = wrap_msg ('pp-prefix', {sepc, pages}, lower);
else
text = wrap_msg ('nopp', {sepc, pages}, lower);
end
end
if is_set (minutes) then
text = pend_separator (wrap_msg ('minutes', minutes, lower), sepc, true) .. text;
else
if is_set (time) then
if not is_set (time_caption) then
text = pend_separator (wrap_msg ('event', time, lower), sepc, true) .. text;
else
text = pend_separator (time_caption .. ' ' .. time .. text, sepc, true);
end
end
end
text = text .. pend_separator (at, sepc, true);
text = text .. pend_separator (wrap_msg ('inset', inset, lower), sepc, true);
if is_set (sections) then
text = text .. pend_separator (wrap_msg ('sections', sections, lower), sepc, true);
elseif is_set (section) then
text = text .. pend_separator (wrap_msg ('section', section, lower), sepc, true);
end
return text;
end
--[[-------------------------< F O R M A T _ P U B L I S H E R >------------------------------------------
]]
local function format_publisher (publisher_name, publication_place, periodical, cite_class, sepc)
local publisher = '';
if is_set (publisher_name) then
if is_set (publication_place) then
publisher = publication_place .. ': ' .. publisher_name;
else
publisher = publisher_name;
end
elseif is_set (publication_place) then
publisher = publication_place;
end
if is_set (publisher) then
if is_set (periodical) and
not in_array (cite_class, {'encyclopaedia', 'web', 'pressrelease', 'podcast'}) then
publisher = ' (' .. publisher .. ')';
else
publisher = pend_separator (publisher, sepc, true);
end
end
return publisher;
end
--[[-------------------------< F O R M A T _ L I N K >-------------------------------------------------
Format an external link that may or may not be raw.
]]
local function format_external_link (text, url_object, sepc)
if is_set (text) then
if is_set (url_object['url']) then
text = make_external_link (url_object['url'], text, url_object['origin']);
end
text = pend_separator (text .. url_object['format'], sepc, true);
elseif is_set (url_object['url']) then
text = make_external_link (url_object['url'], nil, url_object['origin']);
end
return text;
end
--[[-------------------------< F O R M A T _ C O N F E R E N C E >----------------------------------------
]]
local function format_conference (conference, conference_url_object, periodical, cite_class, sepc)
local conf_text = format_external_link (conference, conference_url_object, sepc);
if 'speech' == cite_class and is_set (periodical) then
-- if cite speech, periodical (perhaps because of an included |website= or |journal= parameter) is set;
conf_text = pend_separator (conf_text, sepc, false); -- then add appropriate punctuation to the end of the conference variable if set.
end
return conf_text;
end
--[[--------------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------------------------------
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single Chapter meta-
parameter (chapter_url_source used for error messages).
]]
local function format_chapter_title (scriptchapter, chapter, transchapter, chapter_url_object, no_quotes, cite_class, title_type, sepc)
local chapter_error = '';
if not is_set (chapter) then
chapter = ''; -- to be safe for concatenation
else
if false == no_quotes then
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks
chapter = wrap_style ('quoted-title', chapter);
end
end
chapter = script_concatenate (chapter, scriptchapter) -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
if is_set (transchapter) then
transchapter = wrap_style ('trans-quoted-title', transchapter);
if is_set (chapter) then
chapter = chapter .. ' ' .. transchapter;
else -- here when transchapter without chapter or script-chapter
chapter = transchapter;
chapter_error = ' ' .. set_error ('trans_missing_title', {'chapter'});
end
end
if is_set (chapter_url_object['url']) then
chapter = make_external_link (chapter_url_object['url'], chapter, chapter_url_object['origin']) .. chapter_url_object['access-text'];
-- adds bare_url_missing_title error if appropriate
end
chapter = chapter .. chapter_error;
if is_set (chapter) then
if 'map' == cite_class and is_set (title_type) then
chapter = chapter .. ' ' .. title_type;
end
chapter = pend_separator (chapter .. chapter_url_object['format'], sepc, false);
else -- |chapter= not set but |chapter-format= is so ...
chapter = pend_separator (chapter_url_object['format'], sepc, false); -- ... ChapterFormat has error message, we want to see it
end
return chapter;
end
--[[--------------------------< F O R M A T _ M A I N _ T I T L E >------------------------------------------
Format the five title parameters: |script-title=, |title=, |trans-title=, |title-link=, and |url= into a single Title meta-
parameter (url_origin and title_link_origin used for error messages).
]]
local function format_main_title (title, title_link, title_link_origin, script_title, trans_title, url_object, no_chapter_format, cite_class, periodical)
if is_set (title_link) and is_set (title) then
title = make_internal_link (title_link, title, title_link_origin);
end
if no_chapter_format or
('map' == cite_class and is_set (periodical)) then -- special case for cite map when the map is in a periodical treat as an article
title = kern_quotes (title); -- if necessary, separate title's leading and trailing quote marks from Module provided quote marks
title = wrap_style ('quoted-title', title);
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title= wrap_style ('trans-quoted-title', trans_title );
elseif 'report' == cite_class then -- no styling for cite report
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title= wrap_style ('trans-quoted-title', trans_title ); -- for cite report, use this form for trans-title
else
title = wrap_style ('italic-title', title);
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title = wrap_style ('trans-italic-title', trans_title);
end
local trans_error = '';
if is_set (trans_title) then
if is_set (title) then
trans_title = ' ' .. trans_title;
else
trans_error = ' ' .. set_error ('trans_missing_title', {'title'});
end
end
title = title .. trans_title;
if is_set (title) then
if not is_set (title_link) and is_set (url_object['url']) then
title = make_external_link (url_object['url'], title, url_object['origin']) .. url_object['access-text'] .. trans_error .. url_object['format'];
url_object = create_url_object ();
else
title = title .. trans_error;
end
end
return title, url_object;
end
--[[--------------------------< F O R M A T _ F O R M A T >--------------------------------------------------------
Applies css style to |format=, |chapter-format=, etc. Also emits an error message if the format parameter does
not have a matching url parameter. If the format parameter is not set and the url contains a file extension that
is recognized as a pdf document by MediaWiki's commons.css, this code will set the format parameter to (PDF) with
the appropriate styling.
]]
local function format_format (args)
for _, url_object in pairs (args) do
if is_set (url_object['format']) then
url_object['format'] = wrap_style ('format', url_object['format']); -- add leading space, parenthases, resize
if not is_set (url_object['url']) then
url_object['format'] = url_object['format'] .. set_error ('format_missing_url', {url_object['format-origin'], url_object['origin']});
-- add an error message
end
elseif is_set (url_object['url']) then
if url_object['url']:match ('%.pdf[%?#]?') or url_object['url']:match ('%.PDF[%?#]?') then
-- format is not set so if url is a pdf file then
url_object['format'] = wrap_style ('format', 'PDF'); -- set format to pdf
end
end
end
end
--[[--------------------------< F O R M A T _ A C C E S S D A T E >----------------------------------------------
]]
local function format_accessdate (accessdate, sepc, lower)
if is_set (accessdate) then -- first, wrap in nowrap span if date in appropriate format
if accessdate:match ('^%d%d%d%d%-%d%d%-%d%d$') then
accessdate = wrap_style ('nowrap1', accessdate); -- when accessdate is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.
elseif accessdate:match('^%a+%s*%d%d?,%s+%d%d%d%d$') or accessdate:match ('^%d%d?%s*%a+%s+%d%d%d%d$') then
local cap, cap2 = string.match (accessdate, '^(.*)%s+(%d%d%d%d)$');
accessdate = wrap_style ('nowrap2', {cap, cap2}); -- when accessdate is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY
end
accessdate = ' ' .. wrap_msg ('retrieved', accessdate, lower); -- add retrieved text
accessdate = wrap_style ('accessdate', {sepc, accessdate}); -- allow editors to hide accessdates
end
return accessdate;
end
--[[--------------------------< F O R M A T _ I D >----------------------------------------------------
]]
local function format_id (id, docket, sepc, lower)
id = pend_separator (id, sepc, true);
return pend_separator (wrap_msg ('docket', docket, lower), sepc, true) .. id;
end
--[[--------------------------< F O R M A T _ Q U O T E >----------------------------------------------
]]
local function format_quote (quote, sepc)
if is_set (quote) then
if quote:sub (1, 1) == '"' and quote:sub (-1, -1) == '"' then -- if first and last characters of quote are quote marks
quote = quote:sub (2, -2); -- strip them off
end
return pend_separator (wrap_style ('quoted-text', quote), sepc, true); -- wrap in <q>...</q> tags
end
return '';
end
--[[--------------------------< F O R M A T _ A R C H I V E >------------------------------------------
]]
local function format_archive (archive_url_object, original_url_object, archive_date, dead_url, sepc, lower)
local archived = '';
if is_set (archive_url_object['url']) then
if not is_set (archive_date) then
archive_date = set_error ('archive_missing_date');
end
if in_array (dead_url, cfg.keywords['deadurl-live']) then
local arch_text = cfg.messages['archived'];
if (lower) then arch_text = arch_text:lower(); end;
archived = pend_separator (wrap_msg ('archived-not-dead', {make_external_link (archive_url_object['url'], arch_text, archive_url_object['origin']) .. archive_url_object['format'], archive_date }, lower), sepc, true);
if not is_set (original_url_object['url']) then
archived = archived .. ' ' .. set_error ('archive_missing_url');
end
elseif is_set (original_url_object['url']) then -- dead_url is not live, so it should be empty, dead or unfit
if in_array (dead_url, cfg.keywords['deadurl-unfit']) then
archived = pend_separator (wrap_msg('archived-unfit', archive_date, lower), sepc, true);
-- format already styled
else -- dead_url is empty or dead
archived = pend_separator (wrap_msg ('archived-dead',
{make_external_link (original_url_object['url'], cfg.messages['original'], original_url_object['origin']) .. original_url_object['access-text'] .. original_url_object['format'], archive_date }, lower), sepc, true);
-- format already styled
end
else
archived = pend_separator (wrap_msg ('archived-missing',
{set_error ('archive_missing_url'), archive_date }, lower), sepc, true);
end
elseif is_set (original_url_object['format']) then
archived = original_url_object['format']; -- if set and archive_url not set archive_format has error message
end
return archived;
end
--[[--------------------------< F O R M A T _ L A Y >---------------------------------------------------
]]
local function format_lay (lay_url_object, lay_date, lay_source, sepc, lower)
local lay = '';
if is_set (lay_url_object['url']) then
if is_set (lay_date) then lay_date = ' (' .. lay_date .. ')' end
if is_set (lay_source) then
lay_source = wrap_msg ('lay source', lay_source, lower);
else
lay_source = '';
end
local lay_sum = cfg.messages['lay summary'];
if lower then
lay_sum = lay_sum:lower();
end
lay = pend_separator (make_external_link (lay_url_object['url'], lay_sum, lay_url_object['origin']) .. lay_url_object['format'] .. lay_source .. lay_date, sepc, true);
else -- Test if |lay-format= is given without giving a |lay-url=
lay = pend_separator (lay_url_object['format'], sepc, true); -- if set and LayURL not set, then LayFormat has error message
end
return lay;
end
--[[--------------------------< F O R M A T _ P E R I O D I C A L >------------------------------------
]]
local function format_periodical (periodical, title, title_note, sepc)
if is_set (periodical) then
if is_set (title) or is_set (title_note) then
return pend_separator (wrap_style ('italic-title', periodical), sepc, true);
else
return wrap_style ('italic-title', periodical);
end
end
return '';
end
--[[--------------------------< A N C H O R _ I D >------------------------------------------------------------
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise returns an empty string.
namelist is one of the contributor-, author-, or editor-name lists chosen in that order. year is Year or anchor_year.
]]
local function anchor_id (namelist, year)
local names={}; -- a table for the one to four names and year
for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names
names[i] = v.last
if i == 4 then break end -- if four then done
end
table.insert (names, year); -- add the year at the end
local id = table.concat (names); -- concatenate names and year for CITEREF id
if is_set (id) then -- if concatenation is not an empty string
return 'CITEREF' .. id; -- add the CITEREF portion
else
return ''; -- return an empty string; no reason to include CITEREF id in this citation
end
end
--[[--------------------------< F O R M A T _ C I T A T I O N >--------------------------------------------
]]
local function format_citation (body, cite_class, ref, namelist, year, ocins_output, no_tracking_cats)
local options = {};
if is_set (cite_class) and cite_class ~= 'citation' then
options.class = 'citation ' .. cite_class; -- class=citation required for blue highlight when used with |ref=
else
options.class = 'citation';
end
if is_set (ref) and ref:lower() ~= 'none' then -- set reference anchor if appropriate
local id = ref
if ('harv' == ref ) then
id = anchor_id (namelist, year); -- go make the CITEREF anchor
end
options.id = id;
end
if string.len (body:gsub ('<span[^>/]*>.-</span>', ''):gsub ('%b<>','')) <= 2 then
reset_error ({'err_cats'});
body = set_error ('empty_citation');
reset_error ({'msg_tail'});
end
local text;
if is_set (options.id) then
text = wrap_style ('citation-with-id', {mw.uri.anchorEncode (options.id), mw.text.nowiki (options.class), body});
else
text = wrap_style ('citation-no-id', {mw.text.nowiki (options.class), body});
end
text = text .. wrap_style ('OCinS', ocins_output);
text = text .. make_error_tail (no_tracking_cats); -- append error/maintenance messages/categories to the citation
return text;
end
--[[--------------------------< D E D U C E _ C I T A T I O N _ C L A S S >--------------------------------------
如果citation_class为citation({{citation}}),根据periodical系列参数的设置情况推断实际的引用类型。
]]
local function deduce_citation_class (A, naive_class)
local deduced_class;
local periodical = A['Periodical'];
local origin = A:ORIGIN ('Periodical');
for cite_class, aliases in pairs (cfg.periodical.parameters) do
if cite_class ~= '_general' then
for _, aliase in pairs (aliases) do
if origin == aliase then
deduced_class = cite_class;
end
end
end
end
if (naive_class == 'citation') then
if is_set (deduced_class) then
return deduced_class, true;
end
elseif (naive_class ~= deduced_class) then
local check_list = cfg.periodical.compatibility[naive_class];
if is_set (check_list) then
if is_set (check_list['drop']) and in_array (deduced_class, check_list['drop']) then
A['Periodical'] = discard_parameter (periodical, origin, nil);
elseif is_set (check_list['warn']) and in_array (deduced_class, check_list['warn']) then
append_error ('periodical', {origin, naive_class, deduced_class, check_list['suggest']});
end
end
end
return naive_class, false;
end
--[[--------------------------< A R G U M E N T _ W R A P P E R >----------------------------------------------
Argument wrapper. This function provides support for argument mapping defined in the configuration file so that
multiple names can be transparently aliased to single internal variable.
]]
local function argument_wrapper (args)
local origin = {};
return setmetatable ({
ORIGIN = function (self, k)
local dummy = self[k]; --force the variable to be loaded.
return origin[k];
end
},
{
__index = function (tbl, k)
if origin[k] ~= nil then
return nil;
end
local args, list, v = args, cfg.aliases[k];
if type (list) == 'table' then
v, origin[k] = select_one (args, list, 'redundant_parameters');
if origin[k] == nil then
origin[k] = ''; -- Empty string, not nil
end
elseif list ~= nil then
v, origin[k] = args[list], list;
else
-- maybe let through instead of raising an error?
-- v, origin[k] = args[k], k;
throw_error ('unknown_argument_map');
end
-- Empty strings, not nil;
if v == nil then
v = cfg.defaults[k] or '';
origin[k] = '';
end
tbl = rawset (tbl, k, v);
return v;
end,
});
end
--[[--------------------------< D O _ C I T A T I O N >---------------------------------------------------------
This is the main function doing the majority of the citation formatting.
]]
local function do_citation (config, args)
--local variables that are not cs1 parameters
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language
--[[
Load Input Parameters
The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.
]]
local A = argument_wrapper (args);
local citation_class, did_duduction = deduce_citation_class (A, config.CitationClass);
-- Pick out the relevant fields from the arguments. Different citation templates
-- define different field names for the same underlying things.
------------------------------------------------- Get dates
local Year = A['Year'];
local PublicationDate = A['PublicationDate'];
local OrigYear = A['OrigYear'];
local Date = A['Date'];
local Dateorigin = A:ORIGIN ('Date');
local LayDate = A['LayDate'];
------------------------------------------------- Get title data
local Title = A['Title'];
local ScriptTitle = A['ScriptTitle'];
local Conference = A['Conference'];
local TransTitle = A['TransTitle'];
local TitleNote = A['TitleNote'];
local TitleLink = A['TitleLink'];
local TitleLinkorigin = A:ORIGIN ('TitleLink');
local Periodical = A['Periodical'];
local Periodical_origin = A:ORIGIN ('Periodical'); -- get the name of the periodical parameter
local Series = A['Series'];
local ConferenceURLobject = create_url_object (A['ConferenceURL'], A:ORIGIN ('ConferenceURL'), A['ConferenceFormat'], A:ORIGIN ('ConferenceFormat'));
local ArchiveURLobject = create_url_object (A['ArchiveURL'], A:ORIGIN ('ArchiveURL'), A['ArchiveFormat'], A:ORIGIN ('ArchiveFormat'));
local URLobject = create_url_object (A['URL'], A:ORIGIN ('URL'), A['Format'], A:ORIGIN ('Format'),A['UrlAccess'], A:ORIGIN ('UrlAccess'));
local TranscriptURLobject = create_url_object (A['TranscriptURL'], A:ORIGIN ('TranscriptURL'), A['TranscriptFormat'], A:ORIGIN ('TranscriptFormat'));
local LayURLobject = create_url_object (A['LayURL'], A:ORIGIN ('LayURL'), A['LayFormat'], A:ORIGIN ('LayFormat'));
local Volume = A['Volume'];
local Issue = A['Issue'];
local Page = A['Page'];
local Pages = hyphen_to_dash (A['Pages']);
local At = A['At'];
if not in_array (citation_class, cfg.args_support['templates_using_volume']) then
Volume = discard_parameter (Volume, A:ORIGIN ('Volume'), nil);
end
if not in_array (citation_class, cfg.args_support['templates_using_issue']) then
if (A:ORIGIN ('Issue') ~= 'number') then
Issue = discard_parameter (Issue, A:ORIGIN ('Issue'), nil);
else
Issue = nil;
end
end
if in_array (citation_class, cfg.args_support['templates_not_using_page']) then
Page = discard_parameter (Page, A:ORIGIN ('Page'), nil);
Pages = discard_parameter (Pages, A:ORIGIN ('Pages'), nil);
At = discard_parameter (At, A:ORIGIN ('At'), nil);
end
local Minutes = A['Minutes'];
local Time = A['Time'];
local TimeCaption = A['TimeCaption'];
if not in_array (citation_class, cfg.args_support['templates_involving_time']) then
Minutes = discard_parameter (Minutes, A:ORIGIN ('Minutes'), nil);
Time = discard_parameter (Time, A:ORIGIN ('Time'), nil);
TimeCaption = discard_parameter (TimeCaption, A:ORIGIN ('TimeCaption'), nil);
end
local Sheet = A['Sheet'];
local Sheets = A['Sheets'];
local Section = A['Section'];
local Sections = A['Sections'];
local Inset = A['Inset'];
if not ('map' == citation_class) then
Sheet = discard_parameter (Sheet, A:ORIGIN ('Sheet'), nil);
Sheets = discard_parameter (Sheets, A:ORIGIN ('Sheets'), nil);
Sections = discard_parameter (Sections, A:ORIGIN ('Sections'), nil);
Inset = discard_parameter (Inset, A:ORIGIN ('Inset'), nil);
end
--[[
不知道哪个“天才”想出来的点子,现行引用模板里,section一个参数多个涵义。
在书籍类引用中,section是章节名称,在地图引用中,section是地图的区域编号。
所以一旦知道citation_class不是地图,就可以丢弃上述几乎全部参数,
唯独section参数需要留到检查章节相关参数时一并进行检查。
]]
local Chapter = '';
local ScriptChapter = '';
local TransChapter = '';
local ChapterURLobject;
local no_chapter_format = in_array (citation_class, cfg.args_support['templates_not_using_chapter_format']);
if in_array (citation_class, cfg.args_support['templates_not_using_chapter']) then
ChapterURLobject = create_url_object ();
discard_chapter (A);
if not ('map' == citation_class) then
Section = discard_parameter (Section, A:ORIGIN ('Section'), nil);
end
else
Chapter = A['Chapter'];
ScriptChapter = A['ScriptChapter'];
TransChapter = A['TransChapter'];
ChapterURLobject = create_url_object (A['ChapterURL'], A:ORIGIN ('ChapterURL'), A['ChapterFormat'], A:ORIGIN ('ChapterFormat'), A['ChapterUrlAccess'], A:ORIGIN ('ChapterUrlAccess'));
if is_set (Chapter) then
if is_set (Section) then
select_one (args, {'chapter', 'contribution', 'section'}, 'redundant_parameters');
end
else
Chapter = Section;
Section = nil;
end
end
local Edition = A['Edition'];
local PublicationPlace = A['PublicationPlace']
local Place = A['Place'];
local PublisherName = A['PublisherName'];
local RegistrationRequired = sanitized_parameter_value (A['RegistrationRequired'], A:ORIGIN ('RegistrationRequired'), 'yes_true_y', nil);
local SubscriptionRequired = sanitized_parameter_value (A['SubscriptionRequired'], A:ORIGIN ('SubscriptionRequired'), 'yes_true_y', nil);
local Via = A['Via'];
local AccessDate = A['AccessDate'];
local ArchiveDate = A['ArchiveDate'];
local Agency = A['Agency'];
local DeadURL = sanitized_parameter_value (A['DeadURL'], A:ORIGIN ('DeadURL'), 'deadurl', '');
local Language = A['Language'];
local DoiBroken = A['DoiBroken'];
local ID = A['ID'];
local ASINTLD = A['ASINTLD'];
local IgnoreISBN = sanitized_parameter_value (A['IgnoreISBN'], A:ORIGIN ('IgnoreISBN'), 'yes_true_y', nil);
local Embargo = A['Embargo'];
local Class = A['Class']; -- arxiv class identifier
local ID_list = extract_ids (args);
local ID_access_levels = extract_id_access_levels (args, ID_list);
local LaySource = A['LaySource'];
local Transcript = A['Transcript'];
local no_tracking_cats = set_no_tracking_cats (A['NoTracking'], A:ORIGIN ('NoTracking'), this_page);
local Quote = A['Quote'];
local sepc, PostScript, Ref = set_style (A['Mode'], A:ORIGIN ('Mode'), A['PostScript'], A['Ref'], Quote, config.CitationClass);
if is_set (Quote) and is_set (A['PostScript']) then
select_one (args, {'postscript', 'quote', 'quotation'}, 'redundant_parameters');
end
local use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text
-- check for insource-location-related parameters like |page=, |pages= or |at=. 请注意section参数有歧义,如果section跟书有关系,上面已经被清空了,这里不纳入检查。
select_one (args, {'at', 'time', 'minutes'}, 'redundant_parameters');
select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'time', 'minutes', 'sheet', 'sheets'}, 'redundant_parameters');
if is_set (Section) then
select_one (args, {'at', 'section', 'sections'}, 'redundant_parameters');
else
select_one (args, {'at', 'sections'}, 'redundant_parameters');
end
-- Dummy calls simply to get the error messages and categories
local NoPP = sanitized_parameter_value (A['NoPP'], A:ORIGIN ('NoPP'), 'yes_true_y', nil);
if is_set (Page) then
if is_set (Pages) or is_set (At) then
Pages = ''; -- unset the others
At = '';
end
extra_text_in_parameter_check (Page, 'page'); -- add this page to maint cat if |page= value begins with what looks like p. or pp.
elseif is_set (Pages) then
if is_set (At) then
At = ''; -- unset
end
extra_text_in_parameter_check (Pages, 'page'); -- add this page to maint cat if |pages= value begins with what looks like p. or pp.
end
-- both |publication-place= and |place= (|location=) allowed if different
if not is_set (PublicationPlace) and is_set (Place) then
PublicationPlace = Place; -- promote |place= (|location=) to |publication-place
end
if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same
if is_set (Edition) then
extra_text_in_parameter_check (Edition, 'edition');
end
------------------------------------------------- Get people
local NameListFormat = sanitized_parameter_value (A['NameListFormat'], A:ORIGIN ('NameListFormat'), 'name-list-format', '');
local LastAuthorAmp = sanitized_parameter_value (A['LastAuthorAmp'], A:ORIGIN ('LastAuthorAmp'), 'yes_true_y', nil);
local contributors_valid = in_array (citation_class, cfg.args_support['templates_using_contributor']);
local Authors, Contributors, Editors, Translators, Contribution, NameList, multiple_editors, has_contributors =
get_people (
{
vauthors = A['Vauthors'], authors = A['Authors'], veditors = A['Veditors'], editors = A['Editors'], contribution = A['Contribution'], coauthors = A['Coauthors']
}, {
displayauthors = A['DisplayAuthors'], displayeditors = A['DisplayEditors'], contributorsvalid = contributors_valid, namelistformat = NameListFormat, lastauthoramp = LastAuthorAmp
}, args, this_page.name
); -- (co-)authors, contributors, editors and translators
local TitleType = set_titletype (citation_class, A['TitleType']); -- handle type parameter for those CS1 citations that have default values
-- special case for cite thesis
local Degree = A['Degree'];
if 'thesis' == citation_class then
if (is_set (Degree)) then
TitleType = wrap_msg ('thesis with type', Degree, use_lowercase);
else
TitleType = wrap_msg ('thesis no type', 'placeholder', use_lowercase);
end
else
Degree = discard_parameter (Degree, A:ORIGIN ('Degree'), nil);
end
local Others = A['Others'];
--[[
Parameter remapping for cite encyclopedia:
When the citation has these parameters:
|encyclopedia and |title then map |title to |article and |encyclopedia to |title
|encyclopedia and |article then map |encyclopedia to |title
|encyclopedia then map |encyclopedia to |title
|trans_title maps to |trans_chapter when |title is re-mapped
|url maps to |chapterurl when |title is remapped
All other combinations of |encyclopedia, |title, and |article are not modified
]]
local Encyclopedia;
local Entry = A['Entry'];
if (citation_class == 'encyclopaedia') then -- test code for citation
local entry_redundant = false
Encyclopedia = Periodical;
if is_set (Periodical) then
if is_set (Title) or is_set (ScriptTitle) then
Chapter = Title;
ScriptChapter = ScriptTitle;
ScriptTitle = '';
TransChapter = TransTitle;
TransTitle = '';
ChapterURLobject = URLobject;
URLobject = create_url_object ();
if not is_set (ChapterURLobject['url']) and is_set (TitleLink) then
Chapter = make_internal_link (TitleLink, Chapter, TitleLinkorigin);
end
TitleLink = '';
entry_redundant = is_set (Entry);
elseif is_set (Entry) then
Chapter = Entry;
ChapterURLobject = URLobject;
URLobject = create_url_object ();
end
Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
Periodical = ''; -- redundant so unset
else
if is_set (Title) or is_set (ScriptTitle) then
entry_redundant = is_set (Entry);
else
Title = Entry;
end
end
if entry_redundant then
select_one (args, {'title', 'script-title', 'article', 'entry'}, 'redundant_parameters');
end
else
Entry = discard_parameter (Entry, A:ORIGIN ('Entry'), nil);
end
-- Special case for cite report.
local Docket = A['Docket'];
if citation_class == 'report' then
if is_set (Docket) then
if is_set (ID) then
select_one (args, {'id', 'docket'}, 'redundant_parameters');
end
ID = Docket; -- for cite report when |docket= is set, overwrite ID even if |id= is set
Docket = '';
end
elseif citation_class ~= 'thesis' then
discard_parameter (Docket, A:ORIGIN ('Docket'), '');
end
-- Special case for cite techreport.
local Num = A['Number'];
if citation_class == 'techreport' then -- special case for cite techreport
if is_set (Num) then -- cite techreport uses 'number', which other citations alias to 'issue'
if not is_set (ID) then -- can we use ID for the "number"?
ID = Num; -- yes, use it
else -- ID has a value so emit error message
select_one (args, {'id', 'number'}, 'redundant_parameters');
end
end
elseif not is_set (Issue) then
Num = discard_parameter (Num, A:ORIGIN ('Number'), nil);
end
-- special case for cite interview
local Callsign = A['Callsign'];
local City = A['City'];
local Program = A['Program'];
if (citation_class == 'interview') then
if is_set (Program) then
ID = ' ' .. Program;
end
if is_set (Callsign) then
if is_set (ID) then
ID = ID .. pend_separator (Callsign, sepc, true);
else
ID = ' ' .. Callsign;
end
end
if is_set (City) then
if is_set (ID) then
ID = ID .. pend_separator (City, sepc, true);
else
ID = ' ' .. City;
end
end
if is_set (Others) then
Others = wrap_msg ('interview', {TitleType, Others}, use_lowercase);
TitleType = '';
end
else
Callsign = discard_parameter (Callsign, A:ORIGIN ('Callsign'), nil );
City = discard_parameter (City, A:ORIGIN ('City'), nil );
Program = discard_parameter (Program, A:ORIGIN ('Program'), nil);
end
if is_set (TitleType) then -- if type parameter is specified
TitleType = wrap_msg ('type', TitleType, use_lowercase); -- display it in parentheses
end
-- Account for the oddity that is {{cite conference}} or {{cite speech}}.
local BookTitle = A['BookTitle'];
if 'conference' == citation_class then
if is_set (BookTitle) then
ChapterURLobject = URLobject;
URLobject = create_url_object ();
TransChapter = TransTitle;
TransTitle = '';
Chapter = Title;
Title = BookTitle;
end
else
BookTitle = discard_parameter (BookTitle, A:ORIGIN ('BookTitle'), nil);
if 'speech' == citation_class then
TitleNote = discard_parameter (TitleNote, A:ORIGIN ('TitleNote'), TitleType);
-- override whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).
TitleType = ''; -- annotate the citation
else
Conference = discard_parameter (Conference, A:ORIGIN ('Conference'), '');
-- not cite conference or cite speech so make sure this is empty string
end
end
-- cite map oddities
local Cartography = A['Cartography'];
local Scale = A['Scale'];
if citation_class == 'map' then
Chapter = A['Map'];
TransChapter = A['TransMap'];
ChapterURLobject = create_url_object (A['MapURL'], A:ORIGIN ('MapURL'), A['MapFormat'], A:ORIGIN ('MapFormat'), A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'));
Cartography = pend_separator (wrap_msg ('cartography', Cartography, use_lowercase), sepc, true);
Scale = pend_separator (Scale, sepc, true);
else
Cartography = discard_parameter (Cartography, A:ORIGIN ('Cartography'), '');
Scale = discard_parameter (Scale, A:ORIGIN ('Scale'), '');
discard_parameter (A['Map'], A:ORIGIN ('Map'), nil);
discard_parameter (A['MapURL'], A:ORIGIN ('MapURL'), nil);
discard_parameter (A['TransMap'], A:ORIGIN ('TransMap'), nil);
discard_parameter (A['MapFormat'], A:ORIGIN ('MapFormat'), nil);
discard_parameter (A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'), nil);
end
-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.
if 'episode' == citation_class or 'serial' == citation_class then
local AirDate = A['AirDate'];
local SeriesLink = A['SeriesLink'];
local Network = A['Network'];
local Station = A['Station'];
local s, n = {}, {};
-- do common parameters first
if is_set (Network) then table.insert (n, Network); end
if is_set (Station) then table.insert (n, Station); end
ID = table.concat (n, sepc .. ' ');
if is_set (AirDate) then
if not is_set (Date) then -- promote airdate to date
Date = AirDate;
Dateorigin = A:ORIGIN ('AirDate');
else
select_one (args, {'date', 'air-date', 'airdate'}, 'redundant_parameters');
end
end
if 'episode' == citation_class then -- handle the oddities that are strictly {{cite episode}}
local Season = A['Season'];
local SeriesNumber = A['SeriesNumber'];
if is_set (Season) and is_set (SeriesNumber) then -- these are mutually exclusive so if both are set
select_one (args, {'season', 'series-number', 'series-no', 'seriesnumber', 'seriesno'}, 'redundant_parameters');
-- add error message
SeriesNumber = ''; -- unset; prefer |season= over |seriesno=
end
-- assemble a table of parts concatenated later into Series
if is_set (Season) then table.insert (s, wrap_msg ('season', Season, use_lowercase)); end
if is_set (SeriesNumber) then table.insert (s, wrap_msg ('series', SeriesNumber, use_lowercase)); end
if is_set (Issue) then table.insert (s, wrap_msg ('episode', Issue, use_lowercase)); end
Issue = ''; -- unset because this is not a unique parameter
Chapter = Title; -- promote title parameters to chapter
ScriptChapter = ScriptTitle;
local ChapterLink = TitleLink; -- alias episodelink
local ChapterLinkorigin = TitleLinkorigin;
TransChapter = TransTitle;
ChapterURLobject = URLobject;
Title = Series; -- promote series to title
TitleLink = SeriesLink;
TitleLinkorigin = A:ORIGIN ('SeriesLink');
Series = table.concat (s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number
if is_set (ChapterLink) and not is_set (ChapterURL) then -- link but not URL
Chapter = make_internal_link (ChapterLink, Chapter, ChapterLinkorigin);
-- ok to wikilink
elseif is_set (ChapterLink) and is_set (ChapterURL) then -- if both are set, URL links episode;
Series = make_internal_link (ChapterLink, Series, ChapterLinkorigin);
-- series links with ChapterLink (episodelink -> TitleLink -> ChapterLink) ugly
end
URLobject = create_url_object (); -- unset
TransTitle = '';
ScriptTitle = '';
else -- now oddities that are cite serial
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
if is_set (Series) and is_set (SeriesLink) then
Series = make_internal_link (SeriesLink, Series, A:ORIGIN ('SeriesLink'));
end
Series = wrap_style ('italic-title', Series); -- series is italicized
end
end
-- end of {{cite episode}} stuff
-- Account for the oddities that are {{cite arxiv}}, before generation of COinS data.
if 'arxiv' == citation_class then
if not is_set (ID_list['ARXIV']) then -- |arxiv= or |eprint= required for cite arxiv
append_error ('arxiv_missing', {}); -- add error message
elseif is_set (Series) then -- series is an alias of version
ID_list['ARXIV'] = ID_list['ARXIV'] .. Series; -- concatenate version onto the end of the arxiv identifier
Series = ''; -- unset
deprecated_parameter ('version'); -- deprecated parameter but only for cite arxiv
end
if first_set ({AccessDate, At, URLobject['format'], Page, Pages, PublisherName, URLobject['url'], -- a crude list of parameters that are not supported by cite arxiv
ID_list['ASIN'], ID_list['BIBCODE'], ID_list['DOI'], ID_list['ISBN'], ID_list['ISSN'],
ID_list['JFM'], ID_list['JSTOR'], ID_list['LCCN'], ID_list['MR'], ID_list['OCLC'], ID_list['OL'],
ID_list['OSTI'], ID_list['PMC'], ID_list['PMID'], ID_list['RFC'], ID_list['SSRN'], ID_list['USENETID'], ID_list['ZBL']},27) then
append_error ('arxiv_params_not_supported', {}); -- add error message
AccessDate= ''; -- set these to empty string; not supported in cite arXiv
PublisherName = ''; -- (if the article has been published, use cite journal, or other)
URLobject = create_url_object ();
Page = ''; Pages = ''; At = '';
end
Periodical = 'arXiv'; -- periodical not allowed in cite arxiv; if article has been published, use cite journal
-- set to arXiv for COinS; after that, must be set to empty string
end
-- legacy: promote concatenation of |month=, and |year= to Date if Date not set; or, promote PublicationDate to Date if neither Date nor Year are set.
if not is_set (Date) then
if is_set (Year) then
Date = Year;
Dateorigin = A:ORIGIN ('Year'); -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
elseif is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate;
Dateorigin = A:ORIGIN ('PublicationDate'); -- promote PublicationDate to Date
PublicationDate = '';
end
else
if is_set (PublicationDate) and PublicationDate ~= Date then
PublicationDate = wrap_msg ('publication-date', PublicationDate, use_lowercase);
else
PublicationDate = ''; -- if PublicationDate is same as Date, don't display in rendered citation
end
end
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification
local anchor_year = validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, Dateorigin);
-- used in the CITEREF identifier
-- Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set. Do this after date check but before COInS.
-- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date
Embargo = is_embargoed (Embargo); --
if citation_class == 'journal' and not is_set (URLobject['url']) and is_set (ID_list['PMC']) then
if not is_set (Embargo) then -- if not embargoed or embargo has expired
URLobject['url'] =cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed
URLobject['origin'] = cfg.id_handlers['PMC'].parameters[1]; -- set URLorigin to parameter name for use in error message if citation is missing a |title=
end
end
if not is_set (URLobject['url']) then
if in_array (citation_class, cfg.args_support['templates_requiring_url']) then
append_error ('cite_web_url', {});
end
-- Test if accessdate is given without giving a URL
if is_set (AccessDate) and not is_set (ChapterURLobject['url']) then -- ChapterURL may be set when the others are not set; TODO: move this to a separate test?
append_error ('accessdate_missing_url', {});
AccessDate = '';
end
end
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
-- Test if citation has no title
if not is_set (Title) and
not is_set (TransTitle) and
not is_set (ScriptTitle) then
if 'episode' == citation_class then -- special case for cite episode; TODO: is there a better way to do this?
append_error ('citation_missing_title', {'series'});
else
append_error ('citation_missing_title', {'title'});
end
end
if 'none' == Title and citation_class == 'journal' then -- special case for journal cites
Title = ''; -- set title to empty string
add_maint_cat ('untitled');
end
check_for_external_link ({ -- add error message when any of these parameters contains a URL
['title'] = Title,
[A:ORIGIN ('Chapter')] = Chapter,
[A:ORIGIN ('Periodical')] = Periodical,
[A:ORIGIN ('PublisherName')] = PublisherName,
});
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
-- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that
-- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title
-- is the article title, and Chapter is a section within the article. So, we remap
local coins_chapter = Chapter; -- default assuming that remapping not required
local coins_title = Title; -- et tu
if 'encyclopaedia' == citation_class then
if is_set (Chapter) and is_set (Title) and is_set (Periodical) then -- if all are used then
coins_chapter = Title; -- remap
coins_title = Periodical;
end
end
-- this is the function call to COinS()
local OCinSoutput = COinS ({
['Periodical'] = Periodical,
['Encyclopedia'] = Encyclopedia,
['Chapter'] = coins_chapter,
['ScriptChapter'] = ScriptChapter,
['Map'] = Map,
['Degree'] = Degree; -- cite thesis only
['Title'] = coins_title,
['ScriptTitle'] = ScriptTitle,
['PublicationPlace'] = PublicationPlace,
['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid;
['Season'] = COinS_date.rftssn,
['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit?
['Series'] = Series,
['Volume'] = Volume,
['Issue'] = Issue,
['Pages'] = first_set ({Sheet, Sheets, Page, Pages, At}, 5),
['Edition'] = Edition,
['PublisherName'] = PublisherName,
['URL'] = first_set ({ChapterURLobject['url'], URLobject['url']}, 2),
['Authors'] = NameList,
['ID_list'] = ID_list,
['RawPage'] = this_page.prefixedText,
}, config.CitationClass);
-- Account for the oddities that are {{cite arxiv}}, AFTER generation of COinS data.
if 'arxiv' == citation_class then -- we have set rft.jtitle in COinS to arXiv, now unset so it isn't displayed
Periodical = '';
end
-- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text
if 'newsgroup' == citation_class then
if is_set (PublisherName) then
PublisherName = wrap_msg ('newsgroup', make_external_link ('news:' .. PublisherName, PublisherName, A:ORIGIN ('PublisherName')), use_lowercase);
end
end
-- Now perform various field substitutions.
-- We also add leading spaces and surrounding markup and punctuation to the
-- various parts of the citation, but only when they are non-nil.
-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,
-- an error message if the associated url is not set, or an empty string for concatenation
format_format ({ArchiveURLobject, ConferenceURLobject, URLobject, LayURLobject, TranscriptURLobject, ChapterURLobject});
-- special case for chapter format so no error message or cat when chapter not supported
if format_url_access_text (URLobject, SubscriptionRequired, RegistrationRequired) then
select_one (args, {'url-access', 'urlaccess', 'registration', 'subscription'}, 'redundant_parameters');
end -- 只需其一
format_url_access_text (ChapterURLobject, nil, nil);
local OriginalURLobject; -- TODO: swap chapter and title here so that archive applies to most specific if both are set?
OriginalURLobject, URLobject, ChapterURLobject =
swap_urls (URLobject, ChapterURLobject, ArchiveURLobject, DeadURL);
local chapter_no_quotes = false; -- default assume that we will be quoting the chapter parameter value
if is_set (Contribution) and has_contributors then -- if this is a contribution with contributor(s)
if in_array (Contribution:lower(), cfg.keywords['contribution']) then -- and a generic contribution title
chapter_no_quotes = true; -- then render it unquoted
end
end
Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURLobject, chapter_no_quotes, citation_class, TitleType, sepc);
-- Contribution is also in Chapter
-- Format main title.
Title, URLobject = format_main_title (Title, TitleLink, TitleLinkorigin, ScriptTitle, TransTitle, URLobject, no_chapter_format, citation_class, Periodical);
Place = pend_separator (wrap_msg ('written', Place, use_lowercase), sepc, false);
Conference = format_conference (Conference, ConferenceURLobject, Periodical, citation_class, sepc);
local Insource_location = format_insource_location (Page, Pages, Sheet, Sheets, At, Minutes, Time, TimeCaption, Section, Sections, Inset, citation_class, Periodical_origin, sepc, NoPP, use_lowercase);
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc
Others = pend_separator (Others, sepc, true);
Others = pend_separator (wrap_msg ('translated', Translators, use_lowercase), sepc, true) .. Others;
if 'speech' ~= citation_class then
TitleNote = pend_separator (TitleNote, sepc, true);
end
Edition = wrap_msg ('edition', Edition, use_lowercase);
Series = pend_separator (Series, sepc, true);
OrigYear = wrap_msg ('orig year', OrigYear, use_lowercase);
Agency = pend_separator (Agency, sepc, true);
Volume = format_volume_issue (Volume, Issue, citation_class, Periodical_origin, sepc, use_lowercase);
------------------------------------ totally unrelated data
Via = wrap_msg ('via', Via, use_lowercase);
AccessDate = format_accessdate (AccessDate, sepc, use_lowercase);
ID = format_id (ID, Docket, sepc, use_lowercase);
ID_list = build_id_list (ID_list, {IdAccessLevels=ID_access_levels, DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo, Class = Class});
local URL = '';
if is_set (URLobject['url']) then
URL = ' ' .. make_external_link (URLobject['url'], nil, URLobject['origin']) .. URLobject['access-text'];
end
local Format = URLobject['format'];
Quote = format_quote (Quote, sepc);
local Archived = format_archive (ArchiveURLobject, OriginalURLobject, ArchiveDate, DeadURL, sepc, use_lowercase);
local Lay = format_lay (LayURLobject, LayDate, LaySource, sepc, use_lowercase);
Transcript = format_external_link (Transcript, TranscriptURLobject, sepc);
local Publisher = format_publisher (PublisherName, PublicationPlace, Periodical, citation_class, sepc);
local use_in = is_set (Chapter) and (not has_contributors);
Authors, Editors, Contributors = format_people (Authors, Editors, Contributors, multiple_editors, use_in, sepc);
-- Several of the above rely upon detecting this as nil, so do it last.
Periodical = format_periodical (Periodical, Title, TitleNote, sepc);
-- Piece all bits together at last. Here, all should be non-nil.
-- We build things this way because it is more efficient in LUA
-- not to keep reassigning to the same string variable over and over.
local tcommon;
local tcommon2; -- used for book cite when |contributor= is set
if citation_class == 'journal' and is_set (Periodical) then
Others = pend_separator (Others, sepc, false);
tcommon = safe_join ({Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Edition, Publisher, Agency}, sepc);
elseif contributors_valid then -- special cases for book cites where contributors are allowed
if is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc
tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2
tcommon2 = safe_join ({Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
else
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
end
elseif 'map' == citation_class then -- special cases for cite map
if is_set (Chapter) then -- map in a book; TitleType is part of Chapter
tcommon = safe_join ({Title, Format, Edition, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
elseif is_set (Periodical) then -- map in a periodical
tcommon = safe_join ({Title, TitleType, Format, Periodical, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
else -- a sheet or stand-alone map
tcommon = safe_join ({Title, TitleType, Format, Edition, Scale, Series, Cartography, Others, Publisher}, sepc);
end
elseif 'episode' == citation_class then -- special case for cite episode
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Transcript, Edition, Publisher}, sepc);
else -- all other CS1 templates
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
end
if #ID_list > 0 then
ID_list = safe_join ({sepc .. ' ', table.concat (ID_list, sepc .. ' '), ID}, sepc);
else
ID_list = ID;
end
-- LOCAL
local xDate;
if (is_set (Periodical) and is_set (Date) and
not in_array (citation_class, {'encyclopaedia', 'web'}))
or (in_array (citation_class, {'book', 'news'})) then
if in_array (citation_class, {'journal', 'citation'}) and is_set (Volume) then
xDate = safe_join ({Date .. ',' .. Volume, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
else
xDate = safe_join ({Date, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
end
Insource_location = ''
else
xDate = safe_join ({Date, PublicationDate, OrigYear, AccessDate}, sepc);
end
xDate = pend_separator (xDate, sepc, true);
-- END LOCAL
local idcommon = safe_join ({URL, xDate, ID_list, Archived, Via, Lay, Language, Quote}, sepc);
local text;
if is_set (Authors) then
if is_set (Contributors) then
text = safe_join ({Contributors, Chapter, tcommon, Authors, Place, Editors, tcommon2, Insource_location, idcommon }, sepc);
else
text = safe_join ({Authors, Chapter, Place, Editors, tcommon, Insource_location, idcommon }, sepc);
end
else
text = safe_join ({Editors, Chapter, Place, tcommon, Insource_location, idcommon}, sepc);
end
if is_set (PostScript) and PostScript ~= sepc then
text = safe_join ({text, sepc}, sepc); --Deals with italics, spaces, etc.
text = text:sub (1, -sepc:len()-1);
end
text = safe_join ({text, PostScript}, sepc);
-- Now enclose the whole thing in a <cite/> element
return format_citation (text, config.CitationClass, Ref, NameList, anchor_year, OCinSoutput, no_tracking_cats);
end
--[[--------------------------< V A L I D A T E >--------------------------------------------------------------
Looks for a parameter's name in the whitelist.
Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
local function validate (name)
local name = tostring (name);
local state = whitelist.basic_arguments[name];
-- Normal arguments
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
-- Arguments with numbers in them
name = name:gsub ('%d+', '#'); -- replace digit(s) with # (last25 becomes last#
state = whitelist.numbered_arguments[name];
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
return false; -- Not supported because not found or name is set to nil
end
--[[--------------------------< C I T A T I O N >--------------------------------------------------------------
This is used by templates such as {{cite book}} to create the actual citation text.
]]
function citation (frame)
local pframe = frame:getParent();
local module_path = 'Module:Citation/CS1/'
local module_suffix = frame:getTitle():gsub ('^Module:Citation/CS1', '');
load_modules (module_path, module_suffix);
local args = {};
local suggestions = {};
local error_reported = false;
local config = {};
for k, v in pairs (frame.args) do
config[k] = v;
args[k] = v;
end
local capture; -- the single supported capture when matching unknown parameters using patterns
for k, v in pairs (pframe.args) do
if v ~= '' then
if not validate (k) then
error_reported = false;
if type (k) ~= 'string' then
-- Exclude empty numbered parameters
if v:match ('%S+') ~= nil then
append_error ('text_ignored', {v});
error_reported = true;
end
elseif validate (k:lower()) then
append_error ('parameter_ignored_suggest', {k, k:lower()});
error_reported = true;
else
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData (module_path .. 'Suggestions' .. module_suffix);
end
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
capture = k:match (pattern); -- the whole match if no caputre in pattern else the capture if a match
if capture then -- if the pattern matches
param = substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
append_error ('parameter_ignored_suggest', {k, param});
-- set the error message
error_reported = true;
break;
end
end
if not error_reported then -- couldn't match with a pattern, is there an expicit suggestion?
if suggestions.suggestions[k:lower()] ~= nil then
append_error ('parameter_ignored_suggest', {k, suggestions.suggestions[k:lower()]});
error_reported = true;
else
append_error ('parameter_ignored', {k});
error_reported = true;
end
end
end
end
args[k] = v;
elseif args[k] ~= nil or (k == 'postscript') then
args[k] = v;
end
end
local error_msg;
for k, v in pairs (args) do
if 'string' == type (k) then -- don't evaluate positional parameters
error_msg = has_invisible_chars (k, v);
if is_set (error_msg) then
append_error ('invisible_char', error_msg);
end
end
end
return do_citation (config, args)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {citation = citation};
c5e02f2cabbe93b86a6702b2d17ce44e5a0069d1
Module:Error
828
29
53
2022-07-14T09:52:51Z
zhwp>Xiplus-abot
0
已更改“[[Module:Error]]”的保护设置:高風險模板:143636引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
-- This module implements {{error}}.
local p = {}
local function _error(args)
local message = args.message or args[1] or error('没有指定的-{zh-cn:信息; zh-tw:資訊}-', 2)
message = tostring(message)
local tag = mw.ustring.lower(tostring(args.tag))
-- Work out what html tag we should use.
if not (tag == 'p' or tag == 'span' or tag == 'div') then
tag = 'strong'
end
-- Generate the html.
local root = mw.html.create(tag)
root
:addClass('error')
:wikitext(message)
return tostring(root)
end
function p.error(frame)
local args
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
args = frame.args
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
-- if the message parameter is present but blank, change it to nil so that Lua will
-- consider it false.
if args.message == "" then
args.message = nil
end
return _error(args)
end
return p
64a3fbd57daa8eebfa0f4febc68c915408fd272d
Module:Ilh/data
828
327
679
2022-07-14T09:54:01Z
zhwp>Xiplus-abot
0
已保护“[[Module:Ilh/data]]”:高風險模板:408663引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
return {
['af'] = { ['lang'] = '南非语' },
['am'] = { ['lang'] = '阿姆哈拉语' },
['ami'] = { ['lang-hans'] = '阿美语', ['lang-hant'] = '阿美語' },
['ar'] = { ['lang-hans'] = '阿拉伯语', ['lang-hant'] = '阿拉伯語' },
['az'] = { ['lang'] = '阿塞拜疆语' },
['be'] = { ['lang'] = '白俄羅斯語' },
['be-tarask'] = { ['lang'] = '舊白俄羅斯語' },
['bg'] = { ['lang'] = '保加利亞語' },
['bho'] = { ['lang'] = '博杰普尔语' },
['bn'] = { ['lang'] = '孟加拉語' },
['bo'] = { ['lang'] = '藏语' },
['bs'] = { ['lang'] = '波斯尼亚语' },
['ca'] = { ['lang'] = '加泰罗尼亚语' },
['cdo'] = { ['lang'] = '閩東語' },
['ceb'] = { ['lang'] = '宿霧語' },
['ckb'] = { ['lang'] = '中库尔德语' },
['cs'] = { ['lang'] = '捷克語' },
['cv'] = { ['lang'] = '楚瓦什语' },
['cy'] = { ['lang'] = '威尔士语' },
['da'] = { ['lang'] = '丹麥語' },
['de'] = { ['lang'] = '德语' },
['diq'] = { ['lang'] = '扎扎其语' },
['el'] = { ['lang'] = '希臘語' },
['en'] = { ['lang-hans'] = '英语', ['lang-hant'] = '英語' },
['eo'] = { ['lang'] = '世界语' },
['es'] = { ['lang-hans'] = '西班牙语', ['lang-hant'] = '西班牙語' },
['et'] = { ['lang'] = '爱沙尼亚语' },
['eu'] = { ['lang'] = '巴斯克语' },
['fa'] = { ['lang'] = '波斯語' },
['fi'] = { ['lang'] = '芬蘭語' },
['fo'] = { ['lang'] = '法罗语' },
['fr'] = { ['lang-hans'] = '法语', ['lang-hant'] = '法語' },
['frp'] = { ['lang-hans'] = '阿尔卑坦语', ['lang-hant'] = '阿爾卑坦語' },
['ga'] = { ['lang'] = '愛爾蘭語' },
['gan'] = { ['lang'] = '赣语' },
['gl'] = { ['lang'] = '加利西亞語' },
['gor'] = { ['lang-hans'] = '哥伦打洛文', ['lang-hant'] = '哥倫打洛文' },
['gu'] = { ['lang'] = '古吉拉特語' },
['gv'] = { ['lang'] = '马恩语' },
['hak'] = { ['lang-hans'] = '客家话', ['lang-hant'] = '客家話' },
['he'] = { ['lang'] = '希伯來語' },
['hi'] = { ['lang'] = '印地語' },
['hr'] = { ['lang'] = '克羅地亞語' },
['ht'] = { ['lang'] = '海地克里奥尔语' },
['hu'] = { ['lang'] = '匈牙利语' },
['hy'] = { ['lang'] = '亞美尼亞語' },
['id'] = { ['lang'] = '印度尼西亚语' },
['inh'] = { ['lang-hans'] = '印古什文', ['lang-hant'] = '印古什文' },
['is'] = { ['lang'] = '冰島語' },
['it'] = { ['lang'] = '義大利語' },
['ja'] = { ['lang-hans'] = '日语', ['lang-hant'] = '日語' },
['ka'] = { ['lang'] = '格鲁吉亚语' },
['kk'] = { ['lang'] = '哈萨克语' },
['km'] = { ['lang-hans'] = '高棉语', ['lang-hant'] = '高棉語' },
['ko'] = { ['lang-hans'] = '朝鲜语', ['lang-hant'] = '韓語' },
['ku'] = { ['lang'] = '库尔德语' },
['ky'] = { ['lang'] = '柯爾克孜語' },
['la'] = { ['lang'] = '拉丁語' },
['lad'] = { ['lang'] = '拉迪诺语' },
['lb'] = { ['lang'] = '卢森堡语' },
['lo'] = { ['lang-hans'] = '老挝语', ['lang-hant'] = '寮語' },
['lt'] = { ['lang'] = '立陶宛语' },
['lv'] = { ['lang'] = '拉脫維亞語' },
['lzh'] = { ['lang'] = '文言文' },
['min'] = { ['lang'] = '米南加保语' },
['mk'] = { ['lang-hans'] = '马其顿语', ['lang-hant'] = '馬其頓語' },
['ml'] = { ['lang'] = '马拉雅姆语' },
['mn'] = { ['lang'] = '蒙古語' },
['ms'] = { ['lang'] = '馬來語' },
['mt'] = { ['lang'] = '马耳他语' },
['my'] = { ['lang'] = '缅甸语' },
['na'] = { ['lang'] = '瑙鲁语' },
['nan'] = { ['lang'] = '閩南語' },
['nds'] = { ['lang-hans'] = '低地德语', ['lang-hant'] = '低地德语' },
['ne'] = { ['lang'] = '尼泊尔语' },
['nl'] = { ['lang'] = '荷兰语' },
['no'] = { ['lang'] = '書面挪威語' },
['oc'] = { ['lang'] = '奥克语' },
['pl'] = { ['lang-hans'] = '波兰语', ['lang-hant'] = '波蘭語' },
['ps'] = { ['lang'] = '普什图语' },
['pt'] = { ['lang'] = '葡萄牙語' },
['qu'] = { ['lang-hans'] = '克丘亚语', ['lang-hant'] = '克丘亞語' },
['rm'] = { ['lang'] = '罗曼什语' },
['ro'] = { ['lang'] = '羅馬尼亞語' },
['ru'] = { ['lang'] = '俄语' },
['sa'] = { ['lang-hans'] = '梵语', ['lang-hant'] = '梵語' },
['sh'] = { ['lang'] = '塞爾維亞-克羅地亞語' },
['si'] = { ['lang'] = '僧伽罗语' },
['simple'] = { ['lang'] = '簡單英語' },
['sk'] = { ['lang'] = '斯洛伐克语' },
['sl'] = { ['lang'] = '斯洛維尼亞語' },
['smn'] = { ['lang-hans'] = '伊纳里萨米文', ['lang-hant'] = '伊納里薩米文' },
['so'] = { ['lang'] = '索馬利亞語' },
['sq'] = { ['lang'] = '阿尔巴尼亚语' },
['sr'] = { ['lang'] = '塞尔维亚语' },
['sv'] = { ['lang'] = '瑞典语' },
['sw'] = { ['lang'] = '斯瓦西裡語' },
['szy'] = { ['lang-hans'] = '撒奇莱雅语', ['lang-hant'] = '撒奇萊雅語' },
['ta'] = { ['lang'] = '泰米尔语' },
['tay'] = { ['lang-hans'] = '泰雅语', ['lang-hant'] = '泰雅語' },
['te'] = { ['lang'] = '泰卢固语' },
['tet'] = { ['lang-hans'] = '德顿语', ['lang-hant'] = '德頓語' },
['tg'] = { ['lang'] = '塔吉克语' },
['th'] = { ['lang'] = '泰语' },
['tk'] = { ['lang'] = '土库曼语' },
['tl'] = { ['lang'] = '他加禄语' },
['tr'] = { ['lang'] = '土耳其語' },
['tt'] = { ['lang'] = '韃靼語' },
['tyv'] = { ['lang'] = '图瓦语' },
['uk'] = { ['lang'] = '烏克蘭語' },
['ur'] = { ['lang'] = '烏爾都語' },
['uz'] = { ['lang'] = '烏孜別克语' },
['vi'] = { ['lang'] = '越南语' },
['wuu'] = { ['lang'] = '吴语' },
['xmf'] = { ['lang'] = '明格列尔语' },
['yue'] = { ['lang'] = '粵语' },
}
bf8c13ee2d381d1bbf44f7b305a9b6cefa6692ad
Module:Transclusion count
828
115
224
2022-07-14T09:55:10Z
zhwp>Xiplus
0
Copied content from [[w:en:Special:PermanentLink/1061635767|w:en:Module:Transclusion count]]; see [[w:en:Special:PageHistory/Module:Transclusion count|that page's history]] for attribution; via [[m:User:Xiplus/js/importer.js|importer.js]]
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[那艺娜维基:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
c08ee42f72543653cc35e9f1ae778d67e049f7b4
276
224
2022-07-14T09:55:10Z
zhwp>Xiplus
0
Copied content from [[w:en:Special:PermanentLink/1061635767|w:en:Module:Transclusion count]]; see [[w:en:Special:PageHistory/Module:Transclusion count|that page's history]] for attribution; via [[m:User:Xiplus/js/importer.js|importer.js]]
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[那艺娜维基:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
c08ee42f72543653cc35e9f1ae778d67e049f7b4
398
276
2022-07-14T09:55:10Z
zhwp>Xiplus
0
Copied content from [[w:en:Special:PermanentLink/1061635767|w:en:Module:Transclusion count]]; see [[w:en:Special:PageHistory/Module:Transclusion count|that page's history]] for attribution; via [[m:User:Xiplus/js/importer.js|importer.js]]
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[Wikipedia:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
9b2940dfd623cf550f748fd5bfc25b7f69cd14cd
Module:File link
828
99
192
2022-07-20T20:50:49Z
zhwp>Xiplus-abot
0
已更改“[[Module:File link]]”的保护设置:高風險模板:5001引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
-- This module provides a library for formatting file wikilinks.
local yesno = require('Module:Yesno')
local checkType = require('libraryUtil').checkType
local p = {}
function p._main(args)
checkType('_main', 1, args, 'table')
-- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our
-- own function to get the right error level.
local function checkArg(key, val, level)
if type(val) ~= 'string' then
error(string.format(
"type error in '%s' parameter of '_main' (expected string, got %s)",
key, type(val)
), level)
end
end
local ret = {}
-- Adds a positional parameter to the buffer.
local function addPositional(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#ret + 1] = val
end
-- Adds a named parameter to the buffer. We assume that the parameter name
-- is the same as the argument key.
local function addNamed(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#ret + 1] = key .. '=' .. val
end
-- Filename
checkArg('file', args.file, 3)
ret[#ret + 1] = 'File:' .. args.file
-- Format
if args.format then
checkArg('format', args.format)
if args.formatfile then
checkArg('formatfile', args.formatfile)
ret[#ret + 1] = args.format .. '=' .. args.formatfile
else
ret[#ret + 1] = args.format
end
end
-- Border
if yesno(args.border) then
ret[#ret + 1] = 'border'
end
addPositional('location')
addPositional('alignment')
addPositional('size')
addNamed('upright')
addNamed('link')
addNamed('alt')
addNamed('page')
addNamed('class')
addNamed('lang')
addNamed('start')
addNamed('end')
addNamed('thumbtime')
addPositional('caption')
return string.format('[[%s]]', table.concat(ret, '|'))
end
function p.main(frame)
local origArgs = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:File link'
})
if not origArgs.file then
error("'file' parameter missing from [[Template:File link]]", 0)
end
-- Copy the arguments that were passed to a new table to avoid looking up
-- every possible parameter in the frame object.
local args = {}
for k, v in pairs(origArgs) do
-- Make _BLANK a special argument to add a blank parameter. For use in
-- conditional templates etc. it is useful for blank arguments to be
-- ignored, but we still need a way to specify them so that we can do
-- things like [[File:Example.png|link=]].
if v == '_BLANK' then
v = ''
end
args[k] = v
end
return p._main(args)
end
return p
66925f088d11530f2482f04181a3baaaa0ad3d0c
那艺娜维基:Columns/styles.css
4
25
45
2022-07-23T08:40:25Z
zhwp>Lopullinen
0
从英文版更新
sanitized-css
text/css
@media (min-width: 720px) {
.columns-start .column {
/* @noflip */
float: left;
min-width: 20em;
}
.columns-2 .column {
width: 50%;
}
.columns-3 .column {
width: 33.3%;
}
.columns-4 .column {
width: 25%;
}
.columns-5 .column {
width: 20%;
}
}
da82fb4f7604181dee3116fd03863f7fb2beb7ea
Template:Columns/styles.css
10
53
99
2022-07-23T08:40:25Z
zhwp>Lopullinen
0
从英文版更新
sanitized-css
text/css
@media (min-width: 720px) {
.columns-start .column {
/* @noflip */
float: left;
min-width: 20em;
}
.columns-2 .column {
width: 50%;
}
.columns-3 .column {
width: 33.3%;
}
.columns-4 .column {
width: 25%;
}
.columns-5 .column {
width: 20%;
}
}
da82fb4f7604181dee3116fd03863f7fb2beb7ea
Template:\
10
234
487
2022-08-06T20:50:34Z
zhwp>Xiplus-abot
0
已更改“[[Template:\]]”的保护设置:高風險模板:5001引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
/ <noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
8cbfbe9d6f2aaa7726dfacfb2ee3c213dae39921
Template:請求翻譯句
10
281
586
2022-08-13T00:20:33Z
zhwp>米沙鄢
0
// Edit via Wikiplus
wikitext
text/x-wiki
{{#if:{{{1|<noinclude>+</noinclude>}}}|<mark class="template-facttext" title="需要{{#if:{{{lang|+}}}|從{{ISO 639 name|{{{lang|en}}}}}}}翻譯為中文">{{{1<noinclude>|This is an untranslated statement.</noinclude>}}}</mark>|}}{{fix
|link=Wikipedia:翻譯請求
|title=需要{{#if:{{{lang|+}}}|從{{ISO 639 name|{{{lang|en}}}}}}}翻譯為中文
|text=翻譯請求
|class = noprint Template-Fact
}}{{namespace detect
| main = [[Category:正在翻譯的條目]]{{#if:{{{date|}}}|[[Category:自{{{date}}}正在翻譯的條目]]}}
| template = [[Category:正在翻譯的模板]]
| wikipedia = [[Category:正在翻譯的維基百科頁面]]
| help = [[Category:正在翻譯的維基百科頁面]]
| other = }}<noinclude>{{documentation}}</noinclude>
67fd36bec687174cab506fe70201154767ca0149
Template:Parameter names example
10
221
460
2022-09-30T11:26:54Z
zhwp>PexEric
0
[InPageEdit] 没有编辑摘要
wikitext
text/x-wiki
<includeonly>{{#invoke:Parameter names example|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
de1e29d6ebc113e9d1649ea6a976625885db8a2f
那艺娜维基:If mobile/styles.css
4
13
21
2022-10-13T08:10:53Z
zhwp>A2569875
0
[[WP:UNDO|撤销]][[Special:Contributions/A2569875|A2569875]]([[User talk:A2569875|讨论]])的版本74069131
sanitized-css
text/css
/* Because of how TemplateStyles and MobileFrontend work, it's not possible to
directly test for whether the mobile site is being used in a TemplateStyle. As
such we'll use Minerva as a proxy. This is imperfect. */
body:not(.skin-minerva) .ifmobile > .mobile {
display: none;
}
/*
Force nomobile element to display when present.
Overrides skin-based css for hiding the nomobile class, e.g. Timeless skin with screen size less than 850px.
*/
body.skin-minerva .ifmobile > .nomobile {
display: inherit; /* The fallback */
display: initial;
}
64e9502c6c99627f7760022c2c8ecd83e3699f4a
Template:If mobile/styles.css
10
37
69
2022-10-13T08:10:53Z
zhwp>A2569875
0
[[WP:UNDO|撤销]][[Special:Contributions/A2569875|A2569875]]([[User talk:A2569875|讨论]])的版本74069131
sanitized-css
text/css
/* Because of how TemplateStyles and MobileFrontend work, it's not possible to
directly test for whether the mobile site is being used in a TemplateStyle. As
such we'll use Minerva as a proxy. This is imperfect. */
body:not(.skin-minerva) .ifmobile > .mobile {
display: none;
}
/*
Force nomobile element to display when present.
Overrides skin-based css for hiding the nomobile class, e.g. Timeless skin with screen size less than 850px.
*/
body.skin-minerva .ifmobile > .nomobile {
display: inherit; /* The fallback */
display: initial;
}
64e9502c6c99627f7760022c2c8ecd83e3699f4a
Module:Pagetype/config
828
84
162
2022-12-01T06:29:43Z
zhwp>Xiplus
0
per [[Special:PermaLink/74781310#編輯請求_2022-11-26|EP]] 自[[Module:Pagetype/config/sandbox]]合并[[Special:Contributions/A2569875|A2569875]]的[[Special:PermaLink/74781296|版本74781296]]
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Pagetype configuration data --
-- This page holds localisation and configuration data for Module:Pagetype. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
-- This table holds the values to use for "main=true", "user=true", etc. Keys to
-- this table should be namespace parameters that can be used with
-- [[Module:Namespace detect]].
cfg.pagetypes = {
['main'] = '條目',
['user'] = '用戶頁',
['project'] = '維基百科',
['wikipedia'] = '維基百科',
['wp'] = '維基百科',
['file'] = '-{zh-cn:文件; zh-tw:檔案;}-',
['image'] = '-{zh-cn:文件; zh-tw:檔案;}-',
['mediawiki'] = 'MediaWiki',
['template'] = '模板',
['help'] = '幫助',
['category'] = '分類',
['portal'] = '主題',
['wikiproject'] = '維基專題',
['wpj'] = '維基專題',
['pj'] = '維基專題',
['book'] = '圖書',
['draft'] = '草稿',
['education program'] = '教育課程',
['timedtext'] = '字幕',
['module'] = '-{zh-cn:模块; zh-tw:模組;}-',
['topic'] = '話題',
['talk'] = '討論頁',
['special'] = '特殊頁面',
['media'] = '檔案'
}
-- This table holds the names of the namespaces to be looked up from
-- cfg.pagetypes by default.
cfg.defaultNamespaces = {
'main',
'file',
'template',
'category',
'module',
'book'
}
-- This table holds the names of the namespaces to be looked up from
-- cfg.pagetypes if cfg.defaultnsExtended is set.
cfg.extendedNamespaces = {
'main',
'user',
'project',
'file',
'mediawiki',
'template',
'category',
'help',
'portal',
'wikiproject',
'module',
'book',
'draft'
}
-- The parameter name to set which default namespace values to be looked up from
-- cfg.pagetypes.
cfg.defaultns = 'defaultns'
-- The value of cfg.defaultns to set all namespaces, including talk.
cfg.defaultnsAll = 'all'
-- The value of cfg.defaultns to set the namespaces listed in
-- cfg.extendedNamespaces
cfg.defaultnsExtended = 'extended'
-- The value of cfg.defaultns to set no default namespaces.
cfg.defaultnsNone = 'none'
-- The parameter name to use for disambiguation pages page.
cfg.dab = 'dab'
-- This table holds the different possible aliases for disambiguation-class
-- pages. These should be lower-case.
cfg.dabAliases = {
'disambiguation',
'disambig',
'disamb',
'dab',
'消歧义',
'消歧義'
}
-- The default value for disambiguation pages.
cfg.dabDefault = '页面'
-- The parameter name to use for N/A-class page.
cfg.na = 'na'
-- This table holds the different possible aliases for N/A-class pages. These
-- should be lower-case.
cfg.naAliases = {'na', 'n/a','非条目','非條目'}
-- The default value for N/A-class pages.
cfg.naDefault = '页面'
-- The parameter name to use for redirects.
cfg.redirect = 'redirect'
-- The default value to use for redirects.
cfg.redirectDefault = '重定向'
-- The parameter name for undefined namespaces.
cfg.other = 'other'
-- The value used if the module detects an undefined namespace.
cfg.otherDefault = '页面'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line
7336d20d10f77b58f24be9386797b4823179bf7c
Template:Bot use warning
10
255
527
2022-12-20T16:10:04Z
zhwp>捍粵者
0
修飾語句
wikitext
text/x-wiki
{{Cmbox
|image=[[File:Kawaii robot power clipart.svg|80px|link=那艺娜维基:机器人|alt=]]
|type=notice
|text=<div style="text-align: center;"><span style="font-size: larger;">'''有[[那艺娜维基:机器人|機器人]]使用{{{namespace|本{{Namespace pagename}}}}}{{#ifeq:{{{subcats|}}}|yes|和其子分類}}'''</span>
-----
{{Small|如欲移動、刪除或修改{{{namespace|此{{Namespace pagename}}}}}而無法[[向下兼容|-{zh-hans: 向下兼容; zh-hant:向下相容; }-]],並會影響機器人運作,請先通知機器人操作者,謝謝您。}}{{#if:{{{bot|{{{bots|}}}}}}|{{Small|相關的機器人:{{{bot|{{{bots}}}}}}}}}}</div>}}<includeonly>{{Sandbox other||[[Category:維基百科機器人作業用頁面]]}}</includeonly><noinclude>
{{Documentation}}</noinclude>
9ed7f494880808db1ebcc011fed735628e567783
Template:TemplateDataHeader
10
106
206
2023-01-11T02:53:32Z
zhwp>蕭漫
0
添加重定向模板
wikitext
text/x-wiki
#重定向 [[Template:TemplateData header]]
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
}}
137e325b30019855f5d44e9ad939deb1de931e33
Template:Infobox Douyin personality/doc
10
224
466
2023-01-22T04:56:13Z
zhwp>A1Cafel
0
wikitext
text/x-wiki
{{NoteTA|G1=MediaWiki}}{{Documentation subpage}}<!-- 在本行下編輯模板說明 -->
== 概要 ==
對於[[抖音]]平台人物的條目,此資訊框可能比{{tl|Infobox person}}模板更合適。此模板可用於抖音平台的單人或團體作者。
== 參數及使用方法 ==
=== 有基本参数的空模板 ===
{{Parameter names example|name |logo=|logo_caption |image=Pessoa Neutra.svg |caption |birth_name |birth_date |birth_place |death_date |death_place
|nationality |occupation |website
|pseudonym |channel_name |channel_display_name |years_active |genre
|subscribers |subscriber_date |views |view_date |network |associated_acts |catchphrase(s)
|silver_medal |silver_year |stats_update
}}
<pre style="overflow: auto;">
{{Infobox Douyin personality
| name =
| logo =
| logo_caption =
| image =
| caption =
| birth_name =
| birth_date =
| birth_place =
| death_date =
| death_place =
| nationality =
| occupation =
| website =
| pseudonym =
| channel_url =
| channel_display_name =
| years_active =
| genre =
| subscribers =
| subscriber_date =
| views =
| view_date =
| network =
| associated_acts =
| catchphrase(s) =
| silver_medal =
| silver_year =
| gold_medal =
| gold_year =
| stats_update =
}}
</pre>
The annotated template pattern below shows explanatory comments {{nobr|"<!--×××-->"}} about each specific parameter.
<pre style="overflow: auto;">
{{Infobox Xigua Video personality
| name =
| logo = <!-- just the filename, without the File: or Image: prefix or enclosing [[brackets]] -->
| logo_caption =
| image = <!-- just the filename, without the File: or Image: prefix or enclosing [[brackets]] -->
| caption =
| birth_name = <!-- only use if different from name -->
| birth_date = <!-- {{Birth date and age|YYYY|MM|DD}} or {{Birth-date and age|birth date†}} -->
| birth_place =
| death_date = <!-- {{Death date and age|YYYY|MM|DD|YYYY|MM|DD}} or {{Death-date and age|death date†|birth date†}} -->
| death_place =
| nationality =
| occupation =
| website =
| pseudonym = <!-- use for individuals only -->
<!-- THE FOLLOWING THREE PARAMETERS ARE INTERCHANGEABLE; DO NOT USE TWO OR MORE AT THE SAME TIME -->
| channel_url = <!-- use for channels only, format: space.Xigua Video.com/channel_url -->
| channel_display_name = <!-- if the channel's displayed name differs from the channel_name/channel_url/channel_direct_url -->
| years_active = <!-- year of channel's creation until its discontinuation or present day -->
| genre =
| subscribers =
| subscriber_date = <!-- date at which the given number of subscribers is correct -->
| views =
| view_date = <!-- date at which the given number of views is correct -->
| network = <!-- multi-channel network (MCN) to which the channel has signed (past and/or present), if any -->
| associated_acts =
| catchphrase(s) = <!-- unique phrases said by the Xigua Video uploader -->
| silver_medal = <!-- yes/no; only use if the individual/channel has been awarded with a silver medal by Xigua Video -->
| silver_year = <!-- year in which the channel reached 100,000 subscribers -->
| gold_medal = <!-- yes/no; only use if the individual/channel has been awarded with a gold medal by Xigua Video -->
| gold_year = <!-- year in which the channel reached 1,000,000 subscribers -->
| stats_update = <!-- date at which given channel statistics are correct -->
}}
† birth date and death date may be in either 'DD Month YYYY' or 'Month DD, YYYY'
</pre>
=== 完整的留空参数 ===
{{Parameter names example|header-color|honorific_prefix|name|honorific_suffix|logo|logo_size|logo_alt|logo_caption|image|image_size|alt|caption|birth_name|birth_date|birth_place|death_date|death_place|origin|nationality|education|residence|occupation|height|religion|signature|signature_size|signature_alt|website|pseudonym|channel_name|channel_url|channel_direct_url|channels|creator|location|channel_website|presenter|years_active|genre|subscribers|subscriber_date|views|view_date|network|associated_acts|catchphrase(s)|silver_medal|silver_year|module|module_personal|stats_update|extra_information|nocat}}
<pre style="overflow: auto; white-space: pre-wrap;">
{{Infobox Douyin personality
| header-color =
| honorific_prefix =
| name =
| honorific_suffix =
| logo =
| logo_size =
| logo_alt =
| logo_caption =
| image =
| image_size =
| alt =
| caption =
| birth_name =
| birth_date =
| birth_place =
| death_date =
| death_place =
| origin =
| nationality =
| education =
| residence =
| occupation =
| height =
| religion =
| partner =
| spouse =
| relatives =
| signature =
| signature_size =
| signature_alt =
| website =
| pseudonym =
| channel_url / channels =
| channel_display_name =
| location =
| channel_website =
| creator =
| presenter =
| years_active =
| genre =
| subscribers =
| subscriber_date =
| views =
| view_date =
| network =
| associated_acts =
| catchphrase(s) =
| silver_medal =
| silver_year =
| gold_medal =
| gold_year =
| module =
| module_personal =
| stats_update =
| extra_information =
}}
</pre>
{{Clear}}
== 模板编辑说明 ==
=== 模板数据 ===
{{TemplateData header}}
<templatedata>
{
"params": {
"embed": {
"label": "是否嵌入",
"description": "yes/no"
},
"honorific prefix": {
"label": "敬语前缀"
},
"name": {
"label": "名称"
},
"honorific suffix": {
"label": "敬语后缀"
},
"logo": {
"label": "徽标"
},
"logo_size": {
"label": "徽标大小"
},
"logo_alt": {
"label": "徽标的替代说明文字,给视障用户使用"
},
"logo caption": {
"label": "徽标说明"
},
"image": {
"label": "图像",
"description": "图像名称举例:abc.jpg、xpz.png、123.gif等。如果找不到合适的图像,编者可以在讨论页[[Template:WPBiography]]模板的“needs-photo”栏填写“是”。请不要在此处填写[[File:Replace this image male.svg]]、[[File:Replace this image female.svg]]或其他替代图像。建议使用自由版权图像。"
},
"image size": {
"aliases": [
"imagesize"
],
"label": "图像大小",
"description": "图像大小有如下几种写法:200px(宽度)、x300px(高度)或200x300px(最大宽度和最大长度)。留空或未定义时,会使用默认值frameless(默认为220px,但登录用户可以点击右上角的“参数设置”来调整默认缩略图尺寸)。一般情况下无需填写此参数。"
},
"imagesize": {
"aliases": [
"image size"
],
"label": "图像大小",
"description": "图像大小有如下几种写法:200px(宽度)、x300px(高度)或200x300px(最大宽度和最大长度)。留空或未定义时,会使用默认值frameless(默认为220px,但登录用户可以点击右上角的“参数设置”来调整默认缩略图尺寸)。一般情况下无需填写此参数。"
},
"alt": {
"label": "图像替代",
"description": "图像的替代文字,有助于视力缺陷用户阅读图像内容。参见[[WP:ALT]]。"
},
"image caption": {
"aliases": [
"caption"
],
"label": "图像说明"
},
"header-color": {
"description": "修改表头颜色"
},
"birth_name": {
"label": "生日"
},
"birth_date": {
"label": "出生日期"
},
"birth_place": {
"label": "出生地"
},
"death_date": {
"label": "死亡日期"
},
"death_place": {
"label": "死亡地点"
},
"height": {
"label": "高度"
},
"nationality": {
"label": "国家"
},
"residence": {
"label": "居住地"
},
"occupation": {
"label": "工作"
},
"Origin": {
"label": "出道地点"
},
"education": {
"label": "教育程度"
},
"height_m": {
"label": "身高(公尺)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。以公尺为单位填入(将会自动转换成英制单位)"
},
"height_cm": {
"label": "身高(公分)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。以公分为单位填入(将会自动转换成英制单位)。"
},
"height_ft": {
"label": "身高(英呎)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。与“身高(英吋)”同时使用(将会自动转换成国际单位)。"
},
"height_in": {
"label": "身高(剩馀英吋数字)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。与“身高(英呎)”同时使用,在此填入剩馀的英吋数字(将会自动转换成国际单位)。"
},
"religion": {
"label": "宗教信仰"
},
"partner": {
"label": "伴侣"
},
"spouse": {
"description": "配偶"
},
"signature": {
"aliases": [
"签名"
],
"label": "签名",
"description": "人物签名的图像。请使用图像名称,例如:abc.jpg、xpz.png、123.gif⋯等。"
},
"signature_size": {
"label": "签名尺寸",
"description": "\t\n预设值为 150px。如有必要,签名大小可以在图像大小(\"image_size\")参数中手动调整。"
},
"signature alt": {
"label": "签名替代文字",
"description": "签名图像的替代文本。例如 File:Thomas Jefferson Signature.svg 的替代文本应为“Th: Jefferson”,使其拼写文字与图像内容完全相同。"
},
"website": {
"aliases": [
"homepage",
"URL"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"homepage": {
"aliases": [
"website",
"URL"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"URL": {
"aliases": [
"website",
"homepage"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"pseudonym": {
"label": "别称"
},
"channel_name": {
"label": "频道名称"
},
"channel_url": {
"label": "频道编号"
},
"channel_direct_url": {
"label": "频道编号"
},
"years active": {
"aliases": [
"yearsactive"
],
"label": "活跃时期"
},
"genre": {
"label": "类型"
},
"subscribers": {
"label": "粉丝数"
},
"views": {
"label": "总播放量"
},
"network": {
"label": "包装公司"
},
"associated_acts": {
"label": "相关团体"
},
"catchphrase(s)": {
"label": "口头禅"
},
"channels": {
"label": "频道名称"
},
"creator": {
"label": "创办人"
},
"subscriber_date": {
"label": "粉丝数截止日期"
},
"view_date": {
"label": "统计播放量的截止日期"
},
"stats_update": {
"label": "统计更新时间"
},
"extra_information": {},
"nocat": {},
"Praise quantity": {
"label": "点赞量"
},
"Praise quantity_date": {
"label": "点赞量截止日期"
}
}
}
</templatedata>
{{Film and Television related infobox templates}}
<includeonly>{{Sandbox other||<!-- 本行下加入模板的分類 -->
[[Category:人物信息框模板]]
}}</includeonly>
11a3285c2b943a9fce4eaf3182d3120ff86a62d5
Template:Tlx
10
70
134
2023-02-06T11:34:59Z
zhwp>Xiplus
0
此模板有使用在介面訊息,不支援該語法
wikitext
text/x-wiki
<includeonly><!--
--><code><!--
--><nowiki>{{</nowiki>{{#if:{{{subst|}}} |[[Help:替换引用|subst]]:}}<!--
-->[[{{{LANG|}}}{{{SISTER|}}}{{ns:Template}}:{{{1|}}}|{{{1|}}}]]<!--
-->{{#if:{{{2|}}} ||{{{2}}}}}<!--
-->{{#if:{{{3|}}} ||{{{3}}}}}<!--
-->{{#if:{{{4|}}} ||{{{4}}}}}<!--
-->{{#if:{{{5|}}} ||{{{5}}}}}<!--
-->{{#if:{{{6|}}} ||{{{6}}}}}<!--
-->{{#if:{{{7|}}} ||{{{7}}}}}<!--
-->{{#if:{{{8|}}} ||{{{8}}}}}<!--
-->{{#if:{{{9|}}} ||{{{9}}}}}<!--
-->{{#if:{{{10|}}} ||{{{10}}}}}<!--
-->{{#if:{{{11|}}} ||{{{11}}}}}<!--
-->{{#if:{{{12|}}} ||{{{12}}}}}<!--
-->{{#if:{{{13|}}} ||{{{13}}}}}<!--
-->{{#if:{{{14|}}} ||{{{14}}}}}<!--
-->{{#if:{{{15|}}} ||{{{15}}}}}<!--
-->{{#if:{{{16|}}} ||{{{16}}}}}<!--
-->{{#if:{{{17|}}} ||{{{17}}}}}<!--
-->{{#if:{{{18|}}} ||{{{18}}}}}<!--
-->{{#if:{{{19|}}} ||{{{19}}}}}<!--
-->{{#if:{{{20|}}} ||{{{20}}}}}<!--
-->{{#if:{{{21|}}} ||''...''}}<!--
--><nowiki>}}</nowiki><!--
--></code><!--
--></includeonly><noinclude>
{{Documentation}}</noinclude>
d8d004509af027beddd80b75c1e20c88dfabbc76
Tlx
0
291
605
2023-02-06T11:34:59Z
zhwp>Xiplus
0
此模板有使用在介面訊息,不支援該語法
wikitext
text/x-wiki
<includeonly><!--
--><code><!--
--><nowiki>{{</nowiki>{{#if:{{{subst|}}} |[[Help:替换引用|subst]]:}}<!--
-->[[{{{LANG|}}}{{{SISTER|}}}{{ns:Template}}:{{{1|}}}|{{{1|}}}]]<!--
-->{{#if:{{{2|}}} ||{{{2}}}}}<!--
-->{{#if:{{{3|}}} ||{{{3}}}}}<!--
-->{{#if:{{{4|}}} ||{{{4}}}}}<!--
-->{{#if:{{{5|}}} ||{{{5}}}}}<!--
-->{{#if:{{{6|}}} ||{{{6}}}}}<!--
-->{{#if:{{{7|}}} ||{{{7}}}}}<!--
-->{{#if:{{{8|}}} ||{{{8}}}}}<!--
-->{{#if:{{{9|}}} ||{{{9}}}}}<!--
-->{{#if:{{{10|}}} ||{{{10}}}}}<!--
-->{{#if:{{{11|}}} ||{{{11}}}}}<!--
-->{{#if:{{{12|}}} ||{{{12}}}}}<!--
-->{{#if:{{{13|}}} ||{{{13}}}}}<!--
-->{{#if:{{{14|}}} ||{{{14}}}}}<!--
-->{{#if:{{{15|}}} ||{{{15}}}}}<!--
-->{{#if:{{{16|}}} ||{{{16}}}}}<!--
-->{{#if:{{{17|}}} ||{{{17}}}}}<!--
-->{{#if:{{{18|}}} ||{{{18}}}}}<!--
-->{{#if:{{{19|}}} ||{{{19}}}}}<!--
-->{{#if:{{{20|}}} ||{{{20}}}}}<!--
-->{{#if:{{{21|}}} ||''...''}}<!--
--><nowiki>}}</nowiki><!--
--></code><!--
--></includeonly><noinclude>
{{Documentation}}</noinclude>
d8d004509af027beddd80b75c1e20c88dfabbc76
Module:If empty
828
250
517
2023-02-24T07:02:27Z
zhwp>Xiplus
0
自[[Module:If empty/sandbox]]合并[[Special:Contributions/Great Brightstar|Great Brightstar]]的[[Special:PermaLink/73762716|版本73762716]]
Scribunto
text/plain
local p = {}
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:If empty', removeBlanks = false})
local lastk = 0
for k,v in ipairs(args) do
if v ~= '' then
return v
end
lastk = k
end
end
return p
4bfc0c7c8bf3b63144db1ea12f2260db00421233
Template:Purge
10
319
663
2023-03-03T07:23:15Z
zhwp>Shizhao
0
wikitext
text/x-wiki
[[Special:Purge/{{#if:{{{jumpto|}}}|{{{page|{{FULLPAGENAME}}}}}#{{{jumpto}}}|{{{page|{{FULLPAGENAME}}}}}}}|<span title="{{{2|更新-{zh-hans:服务器;zh-hant:伺服器;}-所-{zh-hans:缓存;zh-hant:快取;}-的页面数据}}}">{{{1|{{int:Purge}}}}}</span>]]<noinclude>{{Documentation}}</noinclude>
4e10b59a9ee84ebe25294f59511297f7821d1360
Template:Markup
10
195
408
2023-03-05T12:44:12Z
zhwp>Great Brightstar
0
wikitext
text/x-wiki
<includeonly>{| style="{{#if:{{{width|}}}|width:{{{width}}};}} margin-top:0;margin-left:{{{margin-left|{{{margin|0}}}}}}; border-width:medium; padding:0; {{{style|}}}"
{{#if:{{{title|{{{標題|{{{标题|}}}}}} }}} |{{!}}+ '''{{{title|{{{標題|{{{标题}}}}}} }}}'''}}
{{#if:{{{noheaders|}}}{{{notitle|{{{無標題|{{{无标题|}}}}}} }}} |
|! scope="col" style="width:50%;{{{colheaderstyle|}}}{{{col1headerstyle|}}}"{{!}} {{{col1|{{{t1|-{zh-cn:代码; zh-tw:原始碼;}-}}}}}} {{!!}}<!--
-->scope="col" style="width:50%;{{{colheaderstyle|}}}{{{col2headerstyle|}}}"{{!}} {{{col2|{{{t2|效果}}}}}}
}}<!--
-->{{#if:{{{1|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{1|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{2|}}} }} }}<!--
-->{{#if:{{{3|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{3|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{4|}}} }} }}<!--
-->{{#if:{{{5|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{5|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{6|}}} }} }}<!--
-->{{#if:{{{7|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{7|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{8|}}} }} }}<!--
-->{{#if:{{{9|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{9|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{10|}}} }} }}<!--
-->{{#if:{{{11|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{11|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{12|}}} }} }}<!--
-->{{#if:{{{13|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{13|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{14|}}} }} }}<!--
-->{{#if:{{{15|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{15|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{16|}}} }} }}<!--
-->{{#if:{{{17|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{17|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{18|}}} }} }}<!--
-->{{#if:{{{19|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{19|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{20|}}} }} }}<!--
-->{{#if:{{{21|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{21|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{22|}}} }} }}<!--
-->{{#if:{{{23|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{23|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{24|}}} }} }}<!--
-->{{#if:{{{25|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{25|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{26|}}} }} }}<!--
-->{{#if:{{{27|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{27|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{28|}}} }} }}<!--
-->{{#if:{{{29|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{29|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{30|}}} }} }}<!--
-->{{#if:{{{31|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{31|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{32|}}} }} }}<!--
-->{{#if:{{{33|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{33|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{34|}}} }} }}<!--
-->{{#if:{{{35|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{35|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{36|}}} }} }}<!--
-->{{#if:{{{37|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{37|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{38|}}} }} }}<!--
-->{{#if:{{{39|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{39|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{40|}}} }} }}
|-
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:#ddd; padding:5px; vertical-align:top;"|
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:#ddd; padding:5px; vertical-align:top;"|
|}</includeonly><noinclude>
{{Documentation}}
</noinclude>
70675bc6fd9a1fdeb95793090bf2af75fb7b518b
Template:Doc
10
275
574
2023-03-07T16:15:56Z
zhwp>蕭漫
0
添加 {{[[Template:Redirect category shell|Redirect category shell]]}} 以顯示保護信息
wikitext
text/x-wiki
#REDIRECT [[Template:Documentation]]
{{Redirect category shell|1=
{{模板重定向}}
{{模板捷徑重定向|'''doc'''umentation|-{zh-hans:文档,文件; zh-hant:文件,文檔;}-}}
}}
1e74c7fcaac4bf434b28d16ae8810ad302871f21
Template:Oldid
10
207
432
2023-03-08T20:51:08Z
zhwp>Xiplus-abot
0
已更改“[[Template:Oldid]]”的保护设置:高風險模板:5455引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
<span class="plainlinks">{{#if:{{{page|{{{1|}}}}}}
|[{{fullurl:{{{page|{{{1}}}}}}|oldid={{{oldid|{{{2|}}}}}} {{{label|{{{4|'''{{{page|{{{1}}}}}}'''的{{{3|{{#if:{{{oldid|{{{2|}}}}}}
|版本{{{oldid|{{{2}}}}}}
|當前版本}}
}}}}}}}}}
}}]
|[[Special:固定链接/{{trim|{{{oldid|{{{2|}}}}}}}}|{{#if:{{{oldid|{{{2|}}}}}}
|{{{label|{{{4|{{{3|歷史版本{{{oldid|{{{2}}}}}}}}}}}}}}}
|{{{label|{{{4|{{{3|Special:固定链接}}}}}}}}}
}}]]
}}</span><noinclude>
{{template doc}}
</noinclude>
1812a13200996d26821a9347bca0c78709670826
Module:Aligned table
828
237
493
2023-04-04T18:04:32Z
zhwp>Qqkuro66541
0
Scribunto
text/plain
--本模塊嵌入{{整齊列表}}
-- This module implements {{aligned table}}
local p = {}
local function isnotempty(s)
return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end
function p.table(frame)
local args = (frame.args[3] ~= nil) and frame.args or frame:getParent().args
local entries = {}
local colclass = {}
local colstyle = {}
local cols = tonumber(args['cols']) or 2
-- create the root table
local root = mw.html.create('table')
-- add table style for fullwidth
if isnotempty(args['fullwidth']) then
root
:css('width', '100%')
:css('border-collapse', 'collapse')
:css('border-spacing', '0px 0px')
:css('border', 'none')
end
-- add table classes
if isnotempty(args['class']) then
root:addClass(args['class'])
end
-- add table style
if isnotempty(args['style']) then
root:cssText(args['style'])
end
-- build arrays with the column styles and classes
if isnotempty(args['leftright']) then
colstyle[1] = 'text-align:left;'
colstyle[2] = 'text-align:right;'
end
if isnotempty(args['rightleft']) then
colstyle[1] = 'text-align:right;'
colstyle[2] = 'text-align:left;'
end
for i = 1,cols do
colclass[ i ] = colclass[ i ] or ''
colstyle[ i ] = colstyle[ i ] or ''
if isnotempty(args['colstyle']) then
colstyle[ i ] = args['colstyle'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colalign' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['colalign' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'align']) then
colstyle[ i ] = 'text-align:' .. args['col' .. tostring(i) .. 'align'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['align' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['align' .. tostring(i)] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colnowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'nowrap']) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['nowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
end
if isnotempty(args['colwidth' .. tostring(i)]) then
colstyle[ i ] = 'width:' .. args['colwidth' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'width']) then
colstyle[ i ] = 'width:' .. args['col' .. tostring(i) .. 'width'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['colwidth']) then
colstyle[ i ] = 'width:' .. args['colwidth'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colstyle' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['colstyle' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'style']) then
colstyle[ i ] = colstyle[ i ] .. args['col' .. tostring(i) .. 'style']
elseif isnotempty(args['style' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['style' .. tostring(i)]
end
if isnotempty(args['colclass' .. tostring(i)]) then
colclass[ i ] = args['colclass' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'class']) then
colclass[ i ] = args['col' .. tostring(i) .. 'class']
elseif isnotempty(args['class' .. tostring(i)]) then
colclass[ i ] = args['class' .. tostring(i)]
end
end
-- compute the maximum cell index
local cellcount = 0
for k, v in pairs( args ) do
if type( k ) == 'number' then
cellcount = math.max(cellcount, k)
end
end
-- compute the number of rows
local rows = math.ceil(cellcount / cols)
-- build the table content
if isnotempty(args['title']) then
local caption = root:tag('caption')
caption:cssText(args['titlestyle'])
caption:wikitext(args['title'])
end
if isnotempty(args['above']) then
local row = root:tag('tr')
local cell = row:tag('th')
cell:attr('colspan', cols)
cell:cssText(args['abovestyle'])
cell:wikitext(args['above'])
end
for j=1,rows do
-- start a new row
local row = root:tag('tr')
if isnotempty(args['rowstyle']) then
row:cssText(args['rowstyle'])
else
row:css('vertical-align', 'top')
end
if isnotempty(args['rowclass']) then
row:addClass(args['rowclass'])
end
-- loop over the cells in the row
for i=1,cols do
local cell
if isnotempty(args['row' .. tostring(j) .. 'header']) then
cell = row:tag('th'):attr('scope','col')
elseif isnotempty(args['col' .. tostring(i) .. 'header']) then
cell = row:tag('th'):attr('scope','row')
else
cell = row:tag('td')
end
if args['class' .. tostring(j) .. '.' .. tostring(i)] then
cell:addClass(args['class' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowclass' .. tostring(j)] then
cell:addClass(args['rowclass' .. tostring(j)])
elseif args['row' .. tostring(j) .. 'class'] then
cell:addClass(args['row' .. tostring(j) .. 'class'])
elseif args['rowevenclass'] and math.fmod(j,2) == 0 then
cell:addClass(args['rowevenclass'])
elseif args['rowoddclass'] and math.fmod(j,2) == 1 then
cell:addClass(args['rowoddclass'])
end
if colclass[i] ~= '' then
cell:addClass(colclass[i])
end
end
if args['style' .. tostring(j) .. '.' .. tostring(i)] then
cell:cssText(args['style' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowstyle' .. tostring(j)] then
cell:cssText(args['rowstyle' .. tostring(j)])
elseif args['rowevenstyle'] and math.fmod(j,2) == 0 then
cell:cssText(args['rowevenstyle'])
elseif args['rowoddstyle'] and math.fmod(j,2) == 1 then
cell:cssText(args['rowoddstyle'])
elseif args['row' .. tostring(j) .. 'style'] then
cell:cssText(args['row' .. tostring(j) .. 'style'])
end
if isnotempty(colstyle[i]) then
cell:cssText(colstyle[i])
end
end
cell:wikitext(mw.ustring.gsub(args[cols*(j - 1) + i] or '', '^(.-)%s*$', '%1') or '')
end
end
-- return the root table
return tostring(root)
end
return p
fd94d5edde4bfa7d961bf37eb56377e2eff6185f
Template:Tlf
10
239
497
2023-04-23T16:38:37Z
zhwp>蕭漫
0
wikitext
text/x-wiki
<includeonly>{{#Invoke:Tlg|main|nowrap=yes|nolink=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlf}}
}}
<!-- 请将分类添加至模板文档(模板文件)页面 -->
</noinclude>
67fc2af930ff6b0605dd6e34058987b73a4b1a85
Flatlist
0
292
607
2023-05-02T12:48:51Z
zhwp>Minorax
0
[[WP:UNDO|撤销]][[Special:Contributions/Minorax|Minorax]]([[User talk:Minorax|讨论]])的版本77070172
wikitext
text/x-wiki
<div class="hlist {{{class|}}}" style="margin-left: {{#expr:{{{indent|0}}}*1.6}}em; {{{style|}}}">{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
be7fa9dab626ef8ba526d6033ec3bc056ab5ff2d
Template:Flatlist
10
300
623
2023-05-02T12:48:51Z
zhwp>Minorax
0
[[WP:UNDO|撤销]][[Special:Contributions/Minorax|Minorax]]([[User talk:Minorax|讨论]])的版本77070172
wikitext
text/x-wiki
<div class="hlist {{{class|}}}" style="margin-left: {{#expr:{{{indent|0}}}*1.6}}em; {{{style|}}}">{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
be7fa9dab626ef8ba526d6033ec3bc056ab5ff2d
UF-hcard-part
0
295
613
2023-05-04T15:39:25Z
zhwp>深鸣
0
地区词转换 // Edit via [[w:zh:WP:MF|WikiMirror]]
wikitext
text/x-wiki
本模板使用了[[HCard|hCard微格式]]標記,被標記的人物或地點資料可以被電腦分析讀取,以便将其自動归類,或者-{zh-hans:通过; zh-hant:透過}-專門的瀏覽器取得資料訊息,例如將訊息加入通訊錄。關於在維基百科使用微格式的詳細訊息,請參見[[WikiProject:微格式|微格式維基專題]]。
出生日期(''bday'')參數只能使用於包含了 {{tl|bd}} 或 {{tl|Birth date and age}} 模板的信息框。
{{flatlist}}
*adr
*bday
*county-name
*'''fn(必須)'''
*geo
*honorific-prefix
*honorific-suffix
*label
*locality
*nickname
*note
*org
*role
*vcard
{{endflatlist}}
'''請不要移除或重新命名這些class。'''
<includeonly>{{sandbox other||
[[Category:使用hCard的模板|{{PAGENAME}}]]
}}</includeonly><noinclude>
{{Documentation |content={{Microformat message templates|state=expanded}}}}
[[Category:微格式信息模板]]
[[Category:使用hCard的模板| ]]
</noinclude>
a31db00f7dbc6e078b4d4ca6fc18dce8c833d4f2
Template:UF-hcard-part
10
302
627
2023-05-04T15:39:25Z
zhwp>深鸣
0
地区词转换 // Edit via [[w:zh:WP:MF|WikiMirror]]
wikitext
text/x-wiki
本模板使用了[[HCard|hCard微格式]]標記,被標記的人物或地點資料可以被電腦分析讀取,以便将其自動归類,或者-{zh-hans:通过; zh-hant:透過}-專門的瀏覽器取得資料訊息,例如將訊息加入通訊錄。關於在維基百科使用微格式的詳細訊息,請參見[[WikiProject:微格式|微格式維基專題]]。
出生日期(''bday'')參數只能使用於包含了 {{tl|bd}} 或 {{tl|Birth date and age}} 模板的信息框。
{{flatlist}}
*adr
*bday
*county-name
*'''fn(必須)'''
*geo
*honorific-prefix
*honorific-suffix
*label
*locality
*nickname
*note
*org
*role
*vcard
{{endflatlist}}
'''請不要移除或重新命名這些class。'''
<includeonly>{{sandbox other||
[[Category:使用hCard的模板|{{PAGENAME}}]]
}}</includeonly><noinclude>
{{Documentation |content={{Microformat message templates|state=expanded}}}}
[[Category:微格式信息模板]]
[[Category:使用hCard的模板| ]]
</noinclude>
a31db00f7dbc6e078b4d4ca6fc18dce8c833d4f2
Template:Hatnote templates
10
116
226
2023-05-20T22:27:30Z
zhwp>Renamed user ZQTozZH8HV
0
// Edit via Wikiplus
wikitext
text/x-wiki
{{Navbox
| name = Hatnote templates
| state = {{{state|<includeonly>autocollapse</includeonly>}}}
| tracking = <includeonly>no</includeonly>
| bodyclass = hlist
| belowclass = hlist
| title = [[那艺娜维基:頂註#頂註模板|頂註模板]]
| above =
* [[那艺娜维基:頂註]]
* [[那艺娜维基:消歧义]]
* [[那艺娜维基:重定向]]
| group1 = 主条目
| list1 =
*{{tl|Main}}
*{{tl|Category main}} (页面分类)
*{{t1|Broader}}
| group2 = 通用
| list2 =
*{{tl|Hatnote}}
*{{tl|Self reference}}([[维基百科:格式手冊/避免自我提及|自我提及]])
| group3 = 其他用法
| list3 =
*{{tl|About}}
*{{tl|Other uses}}
*{{tl|About list}}
| group4 = 关于……
| list4 =
*{{tl|For}}
*{{tl|For2}}(自定义文字)
| group5 = 更多信息
| list5 =
*{{tl|Further}}
*{{tl|Further2}}(自定义文字)
| group6 = 参见
| list6 =
*{{tl|See also}}
*{{tl|Category see also}}
*{{tl|Category see also if exists}}
*{{tl|See Wiktionary}}
| group7 = 地点人物
| list7 =
*{{tl|Other people}}
*{{tl|Other places}}
| group8 = 重定向
| list8 =
*{{tl|Redirect}}
*{{tl|Redirect2}}
*{{tl|Redirect-two}}
*{{tl|Redirect-multi}}
*{{tl|Redirect-synonym}}
*{{tl|Redirect list}}
*{{tl|technical reasons}}
| group9 = 消歧义
| list9 =
*{{tl|Distinguish}}
*{{tl|Distinguish2}}
*{{tl|About-distinguish}}
*{{tl|About-distinguish-text}}(自定义文字)
*{{tl|Redirect-distinguish}}
| group10 = 嵌入
| list10 =
*{{tl|Transcluded section}}
*{{t1|Section transclude}}
| group11 = 个别主题
| list11 =
* {{tl|WikiIPA}}
| group12 = 顶注分类
| list12 =
*[[:Category:頂註模板|頂註模板]]
*[[:Category:頂註模塊|顶注模块]]
*[[:Category:列表顶注模板|列表顶注模板]]
| below =
*[[维基百科:頂註#頂註模板|頂註模板文档]]
*{{Icon|cat}} [[:Category:頂註模板]]
}}<noinclude>{{Documentation}}
</noinclude>
912e3eb834ad857373929ea300df0891e2ce28df
Template:Dummy reference
10
203
424
2023-05-27T11:32:56Z
zhwp>Lopullinen
0
+ param: link
wikitext
text/x-wiki
<sup class="reference nowrap" style="color:#002bb8;">{{#if:{{{link|}}}|[[#{{{link}}}|[{{{1|1}}}]]]|[{{{1|1}}}]}}</sup><noinclude>{{documentation}}</noinclude>
5fa04498a061148cc83f93ef0d7c0e633c5e0f09
MediaWiki:Gadget-Twinkle.css
8
170
342
2023-07-01T12:33:39Z
zhwp>Xiplus
0
Repo at a9cd084: vector-2022: hovering should open menu
css
text/css
/**
* Explicitly set width of TW menu so that we can use a hidden peer gadget
* to add space where the TW menu would go before it loads. See
* twinkle-pagestyles.css
*/
.skin-vector .vector-menu-dropdown #p-twinkle {
width: 3.24em;
}
/**
* In skin vector-2022, open the TW menu when mouse hovers over it. Credit to
* [[en:User:Nardog]] for this fix.
*/
#p-twinkle:hover > .vector-menu-content {
opacity: 1;
visibility: visible;
height: auto;
}
/* twinkleclose.js */
a.twinkle-close-button {
color: red;
font-weight: bold;
}
a.twinkle-close-button-disabled {
color: gray;
}
/* The additional box on user skin.js and twinklepreferences.js pages */
#twinkle-config-headerbox {
border: 1px #f60 solid;
background: #fed;
padding: 0.6em;
margin: 0.5em auto;
text-align: center;
}
/* twinkleoptions.js */
#twinkle-config-headerbox.config-twopt-box {
font-weight: bold;
width: 80%;
border-width: 2px;
}
/* skin-specific js */
#twinkle-config-headerbox.config-userskin-box {
width: 60%;
}
/* TWPREFS */
#twinkle-config-content input[type=checkbox] {
margin-right: 2px;
}
eff02fd157ce62bce708f8ddc24076a98756d7d2
Template:Infobox/doc
10
140
288
2023-07-20T17:48:46Z
zhwp>YFdyh000
0
内容扩充 修饰语句
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{Documentation subpage}}<!-- 请在本页最底部添加分类与跨语言链接。 -->
{{High-use|all-pages=yes}}
{{Lua|Module:Infobox}}
本模板为一系列「信息框」模板的元模板,亦即本模板用于构建其他模板。通常不建議在条目中直接使用此模板,但是如有需要,可以在個別「一次性」情況中直接使用。参见[[Help:信息框]]以获取创建通用信息框的进一步方法。
=== 用法 ===
本模板与{{tl|navbox}}的用法相似,但也有一些不同之处。表格中的每一行既可以是顶栏(header),也可以是成对的标签(label)与-{A|zh-hans:数据; zh-hant:資料;}-(data),甚至还可以只是一个数据单元。每行只能有一种状态,且具有优先级:当你将一行同时定义为顶栏与标签/数据对,那么标签/数据对的定义将会被忽略。
====編號====
為方便日後更改信息框格式,header和label/data行的編號不需要完全按照1、2、3……的加一順序編寫,可以在中間預留一些行編號不用,可避免將來如要增加新行時要把該行後面的行編號一併更改。
header和label/data行的編號不可以重複,例如不可以同時使用header1和label1/data1,請使用header1、label2/data2(舉例)。
如希望大量移動編號(如為加入新label需將所有之後的label數字加一),可考慮使用[[模块:IncrementParams]]。
=== 参数 ===
==== “查看/讨论/编辑/历史”链接 ====
;name : “查看/讨论/编辑/历史”链接需要指向模板页的名称(name)。你可以填写<nowiki>{{subst:PAGENAME}}</nowiki>。如果此参数未填,则“查看/讨论/编辑/历史”链接不会显示。
==== 标题 ====
{{Infobox
|title = 信息框外的标题文本
|data1 = (信息框的其余部分)
}}
{{Infobox
|above = 信息框内的标题文本
|data1 = (信息框的其余部分)
}}
有两种方式为一个信息框填入标题。一种是将标题填在信息框外,另一种则是填写在信息框内。根据需要,你可以选择其中的一种使用,亦或同时使用这两种标题,甚至都不使用(尽管我们不推荐这样做)。
;title : 填写在信息框表格外顶部的标题文本。
;above : 填写在信息框表格内顶部单元的标题文本。
==== 可选项 ====
;subheader : 在 above 下面的次標題。subheader2是第2個次標題。
;image : 在模板上部显示的图像。请使用完整的图像语法,例如<nowiki>[[File:example.png|200px]]</nowiki>,推荐使用[[模块:InfoboxImage]]插入图像。图像的位置默认为居中。<br/>在中文維基百科,一個Infobox最多可使用4個圖像參數:overimage(置頂)、image(=image1)、image2、image3,與英文維基百科的Infobox僅提供image(=image1)、image2不同。
;caption : 位于图像下方的说明文本。<br/>overcaption、caption(=caption1)、caption2、caption3分別對應上面4個圖像參數。
;header(n) : 填入第n行的'''顶栏'''文本。
;label(n): 填入第n行的'''标签'''文本。
;data(n): 填入第n行的'''数据'''文本。
;below: 填写在信息框表格底部单元的文本。底部单元一般用来填写脚注、参见及其他类似的信息。
==== 可选的CSS风格 ====
;bodystyle : 应用到信息框表格全体。
;titlestyle : 应用到信息框表格外的标题中。不建议在此处填写背景颜色(background color),因为该处的文字位于信息框外。
;abovestyle : 应用到信息框表格内顶部单元中。默认的风格为“<syntaxhighlight lang="css" inline>font-size:large;</syntaxhighlight>”(字号设为大号),因为该单元常被用作标题。如果你希望让顶部单元以正常字号显示,只需在该处填写的内容中包含“<syntaxhighlight lang="css" inline>font-size:medium;</syntaxhighlight>”。
;imagestyle : 应用到信息框的图像单元中,包括图像下方的说明文本。但是,出于兼容性与未来修改的考虑,如果你需要设置说明文本的属性,请使用captionstyle而不要使用imagestyle。
;captionstyle : 应用到图像说明文本中。
;headerstyle : 应用到所有的顶栏单元。
;header(n)style : 应用到第n行的顶栏单元。
;labelstyle : 应用到所有的标签单元。如果希望避免标签文字折行显示,只需在该处填写的内容中包含“<syntaxhighlight lang="css" inline>white-space:nowrap;</syntaxhighlight>”。或者例如“min-width: 4em;”。
;label(n)style : 应用到第n行的标签单元。
;datastyle : 应用到所有的数据单元。
;data(n)style : 应用到第n行的数据单元。
;belowstyle : 应用到底部单元中。
==== 微格式 ====
;bodyclass: 该参数影响信息框整体的类(class)。
;imageclass: 该参数影响图像的类。
;class(n): 该参数影响特定行数据单元的类。如果信息框没有数据单元,则不会产生作用。
;titleclass: 该参数影响信息框外标题的类。
;aboveclass: 该参数影响信息框内标题的类。
通过为各个数据单元定义类名,本模板可以支持[[微格式]]信息;此处所说的类名,是根据标准定义的,且可以向机器表明信息的类型。例如,如果一个信息框使用了[[hCard]]的微格式,要在信息框内标记此微格式,则填写以下参数:
<pre>
|bodyclass = vcard
</pre>
并为每一个包含了vcard所需数据单元的行添加相应的类参数:
<pre>
|class1 = fn
|class2 = org
|class3 = tel
</pre>
等等。用于显示信息框主题的“above”和“title”也可以指定类。
请在[[那艺娜维基:專題/微格式]]以获取在维基百科添加微格式信息的进一步信息,访问[http://microformats.org/wiki/Main_Page microformats.org]网站亦能获取更一般性的信息。
=== 表格域可选项 ===
如果表格的一行只有标签而没有数据,那么该行将不会显示。这样可以方便编者创建选填内容的行。要让某行成为可选项,只需填写一个默认为空字段的参数即可:
<pre>
|label5 = 人口
|data5 = {{{population|}}}
</pre>
这样的话,如果在条目中不定义“population”参数,则信息框的那一行不会被显示。
如果表格的一行填写的是预设格式内容(即除了参数外,还有其他内容),而又希望让该行成为可选项的话,你可以通过“#if”语句实现。当参数为空时,令所有的内容均不被呈现。譬如,在下面的例子里,“#if”会判断参数“mass”是否不为空,若不为空则显示它,并跟上“-{A|zh-hans:千克; zh-hant:公斤;}-”的后缀:
<pre>
|label6 = 质量
|data6 = {{#if:{{{mass|}}} |{{{mass}}}千克}}
</pre>
更多关于#if的用法,参见[[Help:模板扩展语法#if|此处]]。
如果你希望顶栏只在其下方的某个或多个数据单元有内容时才显示,以下的例子可以指导你如何实现:
<pre style="overflow:auto;">
{{Infobox
|name = {{subst:PAGENAME}}
|title = 可选顶栏的用例
|autoheaders = y
|header1 = 可选顶栏
|label2 = 项目一
|data2 = {{{item_one|}}}
|label3 = 项目二
|data3 = {{{item_two|}}}
|label4 = 项目三
|data4 = {{{item_three|}}}
}}
</pre>
这样,只有在参数“item_one”、“item_two”或“item_three”其中之一被填写时,“header1”才会被显示。如果上述三个参数均未被定义,则顶栏不会显示。
过去在实现这一功能时,需嵌套冗长的“#if”语法,现在只需设置{{para|autoheaders|y}}即可。
=== 用例 ===
{|style="border: 0px; width: 100%;"
|-
|{{Template Pre
|br = <td style="vertical-align: top;">
|demo_kill_categories =yes
|<nowiki>{{Infobox
|name = Infobox
|bodystyle =
|title = 测试信息框
|titlestyle =
|image = [[File:example.png|200px]]
|imagestyle =
|caption = Caption for example.png
|captionstyle =
|headerstyle = background:#ccf;
|labelstyle = background:#ddf;
|datastyle =
|header1 = 独自定义的顶栏
|label1 =
|data1 =
|header2 =
|label2 = 独自定义的标签
|data2 =
|header3 =
|label3 =
|data3 = 独自定义的数据
|header4 = 三项均有定义(顶栏)
|label4 = 三项均有定义(标签)——错误:因为有设顶栏而不会显示出来
|data4 = 三项均有定义(数据)——错误:因为有设顶栏而不会显示出来
|header5 =
|label5 = 标签和数据有定义(标签)
|data5 = 标签和数据有定义(数据)
|belowstyle = background:#ddf;
|below = 下方文本
}}</nowiki>}}
|}
注意到,当标签脱离数据单元单独定义时,所定义的那一行并未出现在信息框内;而当顶栏与标签、数据定义在同一栏时,顶栏将会优先显示。
{{clear}}
在下面的例子中,定义了“<code>{{nowrap|bodystyle {{=}} width:20em;}}</code>”和“<code>{{nowrap|labelstyle {{=}} width:33%;}}</code>”。
{{Infobox
|bodystyle = width:20em;
|name = Infobox
|title = 测试信息框
|titlestyle =
|headerstyle =
|labelstyle = width:33%;
|datastyle =
|header1 =
|label1 = 标签1
|data1 = 数据1
|header2 =
|label2 = 标签2
|data2 = 数据2
|header3 =
|label3 = 标签3
|data3 = 数据3
|header4 = 顶栏4
|label4 =
|data4 =
|header5 =
|label5 = 标签5
|data5 = 数据5:叽里呱啦稀里哗啦。
|belowstyle =
|below = 下方文本
}}
{{clear}}
=== 完整模板 ===
(备注:本模板目前最多可以同时处理80行表格,一般的信息框模板只会用到前20行的参数,因此此处省略了后60行的参数。需使用时可依此类推。微格式“class”参数亦被省略,因其不常被用到,使用时请自行添加。)
<pre style="overflow:auto;">
{{Infobox
| name = {{subst:PAGENAME}}
| child = {{{child|}}}
| subbox = {{{subbox|}}}
| italic title = {{{italic title|no}}}
| bodystyle =
| titlestyle =
| abovestyle =
| subheaderstyle =
| title =
| above =
| subheader =
| imagestyle =
| captionstyle =
| image =
| caption =
| image2 =
| caption2 =
| headerstyle =
| labelstyle =
| datastyle =
| header1 =
| label1 =
| data1 =
| header2 =
| label2 =
| data2 =
| header3 =
| label3 =
| data3 =
| header4 =
| label4 =
| data4 =
| header5 =
| label5 =
| data5 =
| header6 =
| label6 =
| data6 =
| header7 =
| label7 =
| data7 =
| header8 =
| label8 =
| data8 =
| header9 =
| label9 =
| data9 =
| header10 =
| label10 =
| data10 =
| belowstyle =
| below =
}}
</pre>
=== 参见 ===
* [[Special:前缀索引/Template:Infobox|所有以Template:Infobox为前缀的页面]]
<includeonly>
{{#ifeq:{{SUBPAGENAME}}|sandbox | |
[[Category:信息框模板|*]]
}}
</includeonly>
afea96bb12f9f666f8223d1caf978bdb0f2465c1
Template:Tl
10
81
156
2023-08-12T04:22:51Z
zhwp>Mys 721tx
0
回退到由[[Special:Contributions/Liangent|Liangent]]([[User talk:Liangent|讨论]])做出的修订版本22712444:回退导入版本
wikitext
text/x-wiki
<includeonly>{{[[{{transclude|{{{1}}}}}|{{{1}}}]]{{#if:{{{2|{{{arg|}}}}}}|{{!}}{{{2|{{{arg}}}}}}}}}}</includeonly><noinclude>
{{Documentation}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
db73d4542a3c4808bbcbc2708c654b3bc0834fba
Tl
0
287
597
2023-08-12T04:22:51Z
zhwp>Mys 721tx
0
回退到由[[Special:Contributions/Liangent|Liangent]]([[User talk:Liangent|讨论]])做出的修订版本22712444:回退导入版本
wikitext
text/x-wiki
<includeonly>{{[[{{transclude|{{{1}}}}}|{{{1}}}]]{{#if:{{{2|{{{arg|}}}}}}|{{!}}{{{2|{{{arg}}}}}}}}}}</includeonly><noinclude>
{{Documentation}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
db73d4542a3c4808bbcbc2708c654b3bc0834fba
Template:Jokes
10
329
683
2023-08-17T02:39:07Z
zhwp>Iokseng
0
Iokseng已移動頁面[[Template:Kidding]]至[[Template:Jokes]],不留重新導向
wikitext
text/x-wiki
<noinclude>{{幽默}}</noinclude>{{{{{|safesubst:}}}#ifeq:{{{{{|safesubst:}}}NAMESPACE}}|{{{{{|safesubst:}}}ns:0}}||<span style="background:#ffffdd" title="本句仅作幽默目的,请勿当真。">{{{1|<noinclude>在此处填入幽默语句参数。请勿用作侮辱或人身攻击。</noinclude>}}}</span><sup>[[维基百科:坏笑话和删除的胡话|[{{{2|開玩笑的}}}]]]</sup>}}<noinclude>{{doc}}</noinclude>
4c7ca36a2fb7e1c9bdb9286b1eb6598b82f30feb
Template:開玩笑的
10
321
667
2023-08-17T02:39:30Z
zhwp>Iokseng
0
編輯工具:修復多重重新導向
wikitext
text/x-wiki
#REDIRECT [[Template:Jokes]]
713309a6d9aa0e4ea0f13380895bf9c6dd2f848d
Module:Citation/CS1/Identifiers
828
179
364
2023-08-17T07:22:36Z
zhwp>Shizhao
0
修正笔误
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, wrap_style; -- functions in Module:Citation/CS1/Utilities
local append_error, set_error, throw_error, select_one, add_maint_cat; -- functions in Module:Citation/CS1/Error
local make_internal_link; -- functions in Module:Citation/CS1/Links
local is_valid_date_from_a_point; -- functions in Module:Citation/CS1/Date_validation
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local wd_int_lang = (mw.site.server:match ('wikidata') and mw.getCurrentFrame():preprocess('{{int:lang}}')) or '';
--============================<< H E L P E R F U N C T I O N S >>============================================
--[[--------------------------< E X T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki style external link
警告:该函数与英文站CS1模块中相应函数不兼容,请勿盲目替换!
]]
local function external_link_id(options)
local url_string = options.link_id or options.id;
local ext_link;
if options.encode == true or options.encode == nil then
url_string = mw.uri.encode( url_string );
end
ext_link = mw.ustring.format( '[%s%s%s <span title=\"%s\">%s%s%s</span>]',
options.prefix, url_string, options.suffix or "",
options.link, options.label, options.separator or " ",
mw.text.nowiki(options.id)
);
if is_set (options.access) then
ext_link = wrap_style ('access-signal', {ext_link, cfg.presentation[options.access]}); -- add the free-to-read / paywall lock
end
return ext_link;
end
--[[--------------------------< I N T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki style internal link
]]
local function internal_link_id(options)
return mw.ustring.format( '[[%s%s%s|<span title=\"%s\">%s</span>%s%s]]',
options.prefix, options.id, options.suffix or "",
options.link, options.label, options.separator or " ",
mw.text.nowiki(options.id)
);
end
--[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------
Determines if a PMC identifier's online version is embargoed. Compares the date in |embargo= against today's date. If embargo date is
in the future, returns the content of |embargo=; otherwise, returns and empty string because the embargo has expired or because
|embargo= was not set in this cite.
]]
local function is_embargoed (embargo)
if is_set (embargo) then
local lang = mw.getContentLanguage();
local good1, embargo_date, good2, todays_date;
good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );
good2, todays_date = pcall( lang.formatDate, lang, 'U' );
if good1 and good2 then -- if embargo date and today's date are good dates
if tonumber( embargo_date ) >= tonumber( todays_date ) then -- is embargo date is in the future?
return embargo; -- still embargoed
else
add_maint_cat ('embargo')
return ''; -- unset because embargo has expired
end
end
end
return ''; -- |embargo= not set return empty string
end
--[[--------------------------< IS _ V A L I D _ C H I N E S E _ B O O K _ C A T E G O R Y >----------------------
检查是否为GB/T 9999.1-2018附表B.1规定的合法图书分类
]]
local function is_valid_Chinese_book_category (str)
return in_array (str, {
"A",
"B", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B80", "B82", "B83", "B84", "B9",
"C", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C91", "C92", "C93", "C94", "C95", "C96", "C97",
"D", "D0", "D1", "D2", "D33", "D4", "D5", "D6", "D73", "D8", "D9", "DF",
"E", "E0", "E1", "E2", "E3", "E8", "E9", "E99",
"F", "F0", "F1", "F2", "F3", "F4", "F49", "F5", "F59", "F6", "F7", "F8",
"G", "G0", "G1", "G2", "G3", "G4", "G8",
"H", "H0", "H1", "H2", "H3", "H4", "H5", "H61", "H62", "H63", "H64", "H65", "H66", "H67", "H7", "H81", "H83", "H84", "H9",
"I", "I0", "I1", "I2", "I3", "I7",
"J", "J0", "J1", "J19", "J2", "J29", "J3", "J4", "J5", "J59", "J6", "J7", "J8", "J9",
"K", "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7", "K81", "K85", "K89", "K9",
"N", "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N79", "N8", "N91", "N93", "N94", "N99",
"O", "O1", "O3", "O4", "O6", "O7",
"P", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P9",
"Q", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7", "Q81", "Q89", "Q91", "Q93", "Q94", "Q95", "Q96", "Q98",
"R", "R1", "R2", "R3", "R4", "R5", "R6", "R71", "R72", "R73", "R74", "R75", "R76", "R77", "R78", "R79", "R8", "R9",
"S", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
"T", "TB", "TD", "TE", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TP", "TQ", "TS", "TU", "TV",
"U", "U1", "U2", "U4", "U6", "U8",
"V", "V1", "V2", "V4", "V7",
"X", "X1", "X2", "X3", "X4", "X5", "X7", "X8", "X9",
"Z"
});
end
--[[--------------------------< IS _ V A L I D _ I S X N >-----------------------------------------------------
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit.
ISBN-13 is checked in isbn().
If the number is valid the result will be 0. Before calling this function, issbn/issn must be checked for length
and stripped of dashes, spaces and other non-isxn characters.
]]
local function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58
len = len+1; -- adjust to be a loop counter
for i, v in ipairs( isxn_str ) do -- loop through all of the bytes and calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58)
temp = temp + 10*( len - i ); -- it represents 10 decimal
else
temp = temp + tonumber( string.char(v) )*(len-i);
end
end
return temp % 11 == 0; -- returns true if calculation result is zero
end
--[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >-----------------------------------------------
ISBN-13 and ISMN validator code calculates checksum across all 13 isbn/ismn digits including the check digit.
If the number is valid, the result will be 0. Before calling this function, isbn-13/ismn must be checked for length
and stripped of dashes, spaces and other non-isxn-13 characters.
]]
local function is_valid_isxn_13 (isxn_str)
local temp=0;
isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39
for i, v in ipairs( isxn_str ) do
temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit
end
return temp % 10 == 0; -- sum modulo 10 is zero when isbn-13/ismn is correct
end
--[[--------------------------< N O R M A L I Z E _ L C C N >--------------------------------------------------
lccn normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization)
1. Remove all blanks.
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.
3. If there is a hyphen in the string:
a. Remove it.
b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):
1. All these characters should be digits, and there should be six or less. (not done in this function)
2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.
Returns a normalized lccn for lccn() to validate. There is no error checking (step 3.b.1) performed in this function.
]]
local function normalize_lccn (lccn)
lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace
if nil ~= string.find (lccn,'/') then
lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it
end
local prefix
local suffix
prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix
if nil ~= suffix then -- if there was a hyphen
suffix=string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6
lccn=prefix..suffix; -- reassemble the lccn
end
return lccn;
end
--============================<< I D E N T I F I E R F U N C T I O N S >>====================================
--[[--------------------------< A R X I V >--------------------------------------------------------------------
See: http://arxiv.org/help/arxiv_identifier
format and error check arXiv identifier. There are three valid forms of the identifier:
the first form, valid only between date codes 9108 and 0703 is:
arXiv:<archive>.<class>/<date code><number><version>
where:
<archive> is a string of alpha characters - may be hyphenated; no other punctuation
<class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
first digit of YY for this form can only 9 and 0
<number> is a three-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)
the second form, valid from April 2007 through December 2014 is:
arXiv:<date code>.<number><version>
where:
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
<number> is a four-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces
the third form, valid from January 2015 is:
arXiv:<date code>.<number><version>
where:
<date code> and <version> are as defined for 0704-1412
<number> is a five-digit number
]]
local function arxiv (id, class)
local handler = cfg.id_handlers['ARXIV'];
local year, month, version;
local err_cat = false; -- assume no error message
local text; -- output text
if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9108-0703 format w/ & w/o version
year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month
((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok?
err_cat = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years)
((7 == year) and (4 > month)) then --or -- when year is 07, is month invalid (before April)?
err_cat = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years)
err_cat = true; -- flag for error message
end
else
err_cat = true; -- not a recognized format; flag for error message
end
err_cat = err_cat and table.concat ({' ', set_error ('bad_arxiv')}) or ''; -- set error message if flag is true
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
if is_set (class) then
if id:match ('^%d+') then
text = table.concat ({text, ' [[//arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink
else
text = table.concat ({text, ' ', set_error ('class_ignored')});
end
end
return text;
end
--[[--------------------------< B I B C O D E >--------------------------------------------------------------------
Validates (sort of) and formats a bibcode id.
Format for bibcodes is specified here: http://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes
But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters
and first four digits must be a year. This function makes these tests:
length must be 19 characters
characters in position
1–4 must be digits and must represent a year in the range of 1000 – next year
5 must be a letter
6 must be letter, ampersand, or dot (ampersand cannot directly precede a dot; &. )
7–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. )
9–18 must be letter, digit, or dot
19 must be a letter or dot
]]
local function bibcode (id, access)
local handler = cfg.id_handlers['BIBCODE'];
local err_type;
local year;
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode,
access=access});
if 19 ~= id:len() then
err_type = 'length';
else
year = id:match ("^(%d%d%d%d)[%a][%a&%.][%a&%.%d][%a&%.%d][%a%d%.]+[%a%.]$") --
if not year then -- if nil then no pattern match
err_type = 'value'; -- so value error
else
local next_year = tonumber(os.date ('%Y'))+1; -- get the current year as a number and add one for next year
year = tonumber (year); -- convert year portion of bibcode to a number
if (1000 > year) or (year > next_year) then
err_type = 'year'; -- year out of bounds
end
if id:find('&%.') then
err_type = 'journal'; -- journal abbreviation must not have '&.' (if it does its missing a letter)
end
end
end
if is_set (err_type) then -- if there was an error detected
text = text .. ' ' .. set_error( 'bad_bibcode', {err_type});
end
return text;
end
--[[--------------------------< B I O R X I V >-----------------------------------------------------------------
Format bioRxiv id and do simple error checking. BiorXiv ids are exactly 6 digits.
The bioRxiv id is the number following the last slash in the bioRxiv-issued DOI:
https://doi.org/10.1101/078733 -> 078733
2019年底,biorxiv更换新格式,故而有必要兼容新旧两种格式,对该函数作出针对性修改
]]
local function biorxiv (id)
local handler = cfg.id_handlers['BIORXIV'];
local err_cat = ''; -- presume that bioRxiv id is valid
local invalid = false;
id = id:gsub ("^10.1101/",""); -- doi前缀10.1101/可填可不填,便利用户使用
if nil == id:match ("^%d%d%d%d%d%d$") then -- 不是旧格式
local date_str;
if (nil ~= id:match ("^%d%d%d%d%.[01]%d%.[0-3]%d%.%d%d%d%d%d%d$")) then
date_str = id:match ("^(%d%d%d%d%.[01]%d%.[0-3]%d)%.%d%d%d%d%d%d$");
else
if (nil ~= id:match ("^%d%d%d%d%.[01]%d%.[0-3]%d%.%d%d%d%d%d%dv%d+$")) then
date_str = id:match ("^(%d%d%d%d%.[01]%d%.[0-3]%d)%.%d%d%d%d%d%dv%d+$");
else -- 也不匹配新格式,因而为非法格式
invalid = true;
end
end
if (not invalid) then
date_str = date_str:gsub ("%.", "-");
if(not is_valid_date_from_a_point(date_str, 1576022400)) then
invalid = true;
end
end
end
if (invalid) then
err_cat = ' ' .. set_error( 'bad_biorxiv'); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix = handler.prefix, id = "10.1101/" .. id, separator = handler.separator,
encode = handler.encode, access = handler.access}) .. err_cat;
end
--[[--------------------------< C I T E S E E R X >------------------------------------------------------------
CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org).
The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure
]]
local function citeseerx (id)
local handler = cfg.id_handlers['CITESEERX'];
local matched;
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode,
access=handler.access});
matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$");
if not matched then
text = text .. ' ' .. set_error( 'bad_citeseerx' );
end
return text;
end
--[[--------------------------< C N I D >----------------------------------------------------------------------
判断国内统一刊号的合法性及输出相关内容
]]
local function cnid (id)
local handler = cfg.id_handlers['CNID'];
local text;
local type = 0;
local invalid = false;
local AA, BBBB, CC;
id = id:gsub ("^CN ?", "");
if nil ~= id:match ("^%d%d%-%d%d%d%d$") then
AA, BBBB = id:match ("^(%d%d)%-(%d%d%d%d)$");
else
if nil ~= id:match ("^%d%d%-%d%d%d%d/[A-Z0-9]+$") then
AA, BBBB, CC = id:match ("^(%d%d)%-(%d%d%d%d)/([A-Z0-9]+)$")
else invalid = true;
end
end
if (not invalid) then
if not in_array (AA, {"09", "10", "11", -- 北京
"12", "13", "14", "15", -- 华北
"21", "22", "23", -- 东北
"30", "31", "32", "33", "34", "35", "36", "37", -- 华东
"41", "42", "43", "44", "45", "46", -- 华中华南
"50", "51", "52", "53", "54", -- 西南
"61", "62", "63", "64", "65" -- 西北
}) then
invalid = true ;
else
local BBBB_num = tonumber (BBBB);
if (BBBB_num >= 1 and BBBB_num <= 999) then
type = 1;
if (nil ~= CC) then
invalid = true;
end;
else
if (BBBB_num >= 1000 and BBBB_num <= 5999) then
type = 2;
if (not is_valid_Chinese_book_category (CC)) then
invalid = true;
end
else
type = 3;
if (nil ~= CC and not is_valid_Chinese_book_category (CC)) then
invalid = true;
end
end
end
end
end
if (not invalid) and (1 == type) then
local link_id = id:gsub ("-","");
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix, suffix = "&typeNum=1",
link_id = link_id, id = id,
separator = handler.separator, encode = handler.encode});
else
if (not invalid) and (2 == type) then
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix, suffix = "&typeNum=2",
id = id, separator = handler.separator, encode = handler.encode});
else
text = mw.ustring.format( "<span title=\"%s\">%s%s%s</span>",
handler.link, handler.label, handler.separator,
mw.text.nowiki (id)
);
end
end
if (invalid) then
text = text .. ' ' .. set_error( 'bad_cnid');
end
return text;
end
--[[--------------------------< C S B N >----------------------------------------------------------------------
判断CSBN的合法性及产生指向豆瓣网的链接。
CSBN格式参考《谈谈国家统一书号与国际标准书号》及最新实例。
]]
local function csbn_checkCatNum (cat)
local cat_num = tonumber(cat)
return not (cat_num <=0 or cat_num >17) -- 若分类号取值不在1-17范围内,则不合法。
end
local function csbn (id)
local handler = cfg.id_handlers['CSBN'];
local text;
local invalid = false;
id = id:gsub ("%-","·");
if (nil == id:match ("^[1-9]%d?%d?%d?%d%d%d·%d+$")) then
-- CSBN由三部分组成,第一部分为中国人民大学图书分类法代号,取值1-17(前缀不补零);
-- 第二部分为出版社代号,三到五位;第三部分为种次号,取值不限。
-- 二、三部分间有小圆点;若取值不合该格式,则不合法。
-- 此外,虽然小圆点用"-"取代不合规定,但误用较多,亦有出版物采用,故兼容。
invalid = true;
else
local catNumOk = nil
local category
category = id:match ("^([1-9]%d-)%d?%d?%d%d%d·%d+$"); -- Lua无法非贪婪特定部分或指定重复次数,分别检查
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
category = id:match ("^([1-9]%d-)%d?%d%d%d·%d+$");
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
category = id:match ("^([1-9]%d-)d%d%d·%d+$");
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
invalid = not catNumOk;
end
-- 豆瓣网以连接号取代小圆点,故替换之。
local link_id = id:gsub ("·","%-");
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix,
link_id = link_id, id = id,
separator = handler.separator, encode = handler.encode});
if (invalid) then
text = text .. ' ' .. set_error( 'bad_csbn');
end
return text;
end
--[[--------------------------< D O I >------------------------------------------------------------------------
Formats a DOI and checks for DOI errors.
DOI names contain two parts: prefix and suffix separated by a forward slash.
Prefix: directory indicator '10.' followed by a registrant code
Suffix: character string of any length chosen by the registrant
This function checks a DOI name for: prefix/suffix. If the doi name contains spaces or endashes, or, if it ends
with a period or a comma, this function will emit a bad_doi error message.
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in doi names.
]]
local function doi(id, inactive, access)
local cat = ""
local handler = cfg.id_handlers['DOI'];
local text;
if is_set(inactive) then
local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date
if is_set(inactive_year) then
set_error('doi_inactive_dated', {inactive_year});
else
set_error('doi_inactive'); -- when inactive doesn't contain a recognizable year
end
inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=access}) .. (inactive or '')
if nil == id:match("^10%.[^%s–]-/[^%s–]-[^%.,]$") then -- doi must begin with '10.', must contain a fwd slash, must not contain spaces or endashes, and must not end with period or comma
cat = ' ' .. set_error( 'bad_doi' );
end
return text .. cat
end
--[[--------------------------< H D L >------------------------------------------------------------------------
Formats an HDL with minor error checking.
HDL names contain two parts: prefix and suffix separated by a forward slash.
Prefix: character string using any character in the UCS-2 character set except '/'
Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant
This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends
with a period or a comma, this function will emit a bad_hdl error message.
HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and
terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in HDLs.
]]
local function hdl(id, access)
local handler = cfg.id_handlers['HDL'];
local text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=access})
if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- hdl must contain a fwd slash, must not contain spaces, endashes, and must not end with period or comma
text = text .. ' ' .. set_error( 'bad_hdl' );
end
return text;
end
--[[--------------------------< I S B N >----------------------------------------------------------------------
Determines whether an ISBN string is valid
]]
local function isbn( isbn_str )
if nil ~= isbn_str:match("[^%s-0-9X]") then
return false, 'invalid character'; -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
end
isbn_str = isbn_str:gsub( "-", "" ):gsub( " ", "" ); -- remove hyphens and spaces
local len = isbn_str:len();
if len ~= 10 and len ~= 13 then
return false, 'length'; -- fail if incorrect length
end
if len == 10 then
if isbn_str:match( "^%d*X?$" ) == nil then -- fail if isbn_str has 'X' anywhere but last position
return false, 'invalid form';
end
return is_valid_isxn(isbn_str, 10), 'checksum';
else
if isbn_str:match( "^%d+$" ) == nil then
return false, 'invalid character'; -- fail if isbn13 is not all digits
end
if isbn_str:match( "^97[89]%d*$" ) == nil then
return false, 'invalid prefix'; -- fail when isbn13 does not begin with 978 or 979
end
return is_valid_isxn_13 (isbn_str), 'checksum';
end
end
--[[--------------------------< A M A Z O N >------------------------------------------------------------------
Formats a link to Amazon. Do simple error checking: asin must be mix of 10 numeric or uppercase alpha
characters. If a mix, first character must be uppercase alpha; if all numeric, asins must be 10-digit
isbn. If 10-digit isbn, add a maintenance category so a bot or awb script can replace |asin= with |isbn=.
Error message if not 10 characters, if not isbn10, if mixed and first character is a digit.
This function is positioned here because it calls isbn()
]]
local function asin(id, domain)
local err_cat = ""
if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then
err_cat = ' ' .. set_error ('bad_asin'); -- asin is not a mix of 10 uppercase alpha and numeric characters
else
if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X)
if isbn( id ) then -- see if asin value is isbn10
add_maint_cat ('ASIN');
elseif not is_set (err_cat) then
err_cat = ' ' .. set_error ('bad_asin'); -- asin is not isbn10
end
elseif not id:match("^%u[%d%u]+$") then
err_cat = ' ' .. set_error ('bad_asin'); -- asin doesn't begin with uppercase alpha
end
end
if not is_set(domain) then
domain = "com";
elseif in_array (domain, {'jp', 'uk'}) then -- Japan, United Kingdom
domain = "co." .. domain;
elseif in_array (domain, {'au', 'br', 'mx'}) then -- Australia, Brazil, Mexico
domain = "com." .. domain;
end
local handler = cfg.id_handlers['ASIN'];
return external_link_id({link=handler.link,
label=handler.label, q = handler.q, prefix=handler.prefix .. domain .. "/dp/",
id=id, encode=handler.encode, separator = handler.separator}) .. err_cat;
end
--[[--------------------------< I S M N >----------------------------------------------------------------------
Determines whether an ISMN string is valid. Similar to isbn-13, ismn is 13 digits begining 979-0-... and uses the
same check digit calculations. See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf
section 2, pages 9–12.
]]
local function ismn (id)
local handler = cfg.id_handlers['ISMN'];
local text;
local valid_ismn = true;
local id_copy;
id_copy = id; -- save a copy because this testing is destructive
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the ismn
if 13 ~= id:len() or id:match( "^9790%d*$" ) == nil then -- ismn must be 13 digits and begin 9790
valid_ismn = false;
else
valid_ismn=is_valid_isxn_13 (id); -- validate ismn
end
-- text = internal_link_id({link = handler.link, label = handler.label, -- use this (or external version) when there is some place to link to
-- prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
text="[[" .. handler.link .. "|" .. handler.label .. "]]" .. handler.separator .. id;
-- because no place to link to yet
if false == valid_ismn then
text = text .. ' ' .. set_error( 'bad_ismn' ) -- add an error message if the issn is invalid
end
return text;
end
--[[--------------------------< I S S N >----------------------------------------------------------------------
Validate and format an issn. This code fixes the case where an editor has included an ISSN in the citation but
has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked
like this:
|issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link
This code now prevents that by inserting a hyphen at the issn midpoint. It also validates the issn for length
and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check issn error message. The
issn is always displayed with a hyphen, even if the issn was given as a single group of 8 digits.
]]
local function issn(id, e)
local issn_copy = id; -- save a copy of unadulterated issn; use this version for display if issn does not validate
local handler;
local text;
local valid_issn = true;
if e then
handler = cfg.id_handlers['EISSN'];
else
handler = cfg.id_handlers['ISSN'];
end
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the issn
if 8 ~= id:len() or nil == id:match( "^%d*X?$" ) then -- validate the issn: 8 digits long, containing only 0-9 or X in the last position
valid_issn=false; -- wrong length or improper character
else
valid_issn=is_valid_isxn(id, 8); -- validate issn
end
if true == valid_issn then
id = string.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 ); -- if valid, display correctly formatted version
else
id = issn_copy; -- if not valid, use the show the invalid issn with error message
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if false == valid_issn then
text = text .. ' ' .. set_error( 'bad_issn', e and 'e' or '' ) -- add an error message if the issn is invalid
end
return text
end
--[[--------------------------< J F M >-----------------------------------------------------------------------
A numerical identifier in the form nn.nnnn.nn
]]
local function jfm (id)
local handler = cfg.id_handlers['JFM'];
local id_num;
local err_cat = '';
id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier
if is_set (id_num) then
add_maint_cat ('jfm_format');
else -- plain number without mr prefix
id_num = id; -- if here id does not have prefix
end
if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then
id = id_num; -- jfm matches pattern
else
err_cat = ' ' .. set_error( 'bad_jfm' ); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< L C C N >----------------------------------------------------------------------
Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.
http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:lccn/
length = 8 then all digits
length = 9 then lccn[1] is lower case alpha
length = 10 then lccn[1] and lccn[2] are both lower case alpha or both digits
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lower case alpha or both digits
length = 12 then lccn[1] and lccn[2] are both lower case alpha
]]
local function lccn(lccn)
local handler = cfg.id_handlers['LCCN'];
local err_cat = ''; -- presume that LCCN is valid
local id = lccn; -- local copy of the lccn
id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes)
local len = id:len(); -- get the length of the lccn
if 8 == len then
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits)
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 9 == len then -- LCCN should be adddddddd
if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern?
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ...
if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
end
elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd
if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
elseif 12 == len then -- LCCN should be aadddddddddd
if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
else
err_cat = ' ' .. set_error( 'bad_lccn' ); -- wrong length, set an error message
end
if not is_set (err_cat) and nil ~= lccn:find ('%s') then
err_cat = ' ' .. set_error( 'bad_lccn' ); -- lccn contains a space, set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=lccn,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< M R >--------------------------------------------------------------------------
A seven digit number; if not seven digits, zero-fill leading digits to make seven digits.
]]
local function mr (id)
local handler = cfg.id_handlers['MR'];
local id_num;
local id_len;
local err_cat = '';
id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix
if is_set (id_num) then
add_maint_cat ('mr_format');
else -- plain number without mr prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
id_len = id_num and id_num:len() or 0;
if (7 >= id_len) and (0 ~= id_len) then
id = string.rep ('0', 7-id_len ) .. id_num; -- zero-fill leading digits
else
err_cat = ' ' .. set_error( 'bad_mr' ); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< O C L C >----------------------------------------------------------------------
Validate and format an oclc id. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}}
archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html
]]
local function oclc (id)
local handler = cfg.id_handlers['OCLC'];
local number;
local err_msg = ''; -- empty string for concatenation
if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters)
number = id:match('ocm(%d+)'); -- get the number
elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters)
number = id:match('ocn(%d+)'); -- get the number
elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters)
number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number
elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field
number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number
if 9 < number:len() then
number = nil; -- contrain to 1 to 9 digits; change this when oclc issues 10-digit numbers
end
elseif id:match('^%d+$') then -- no prefix
number = id; -- get the number
if 10 < number:len() then
number = nil; -- contrain to 1 to 10 digits; change this when oclc issues 11-digit numbers
end
end
if number then -- proper format
id = number; -- exclude prefix, if any, from external link
else
err_msg = ' ' .. set_error( 'bad_oclc' ) -- add an error message if the id is malformed
end
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode}) .. err_msg;
return text;
end
--[[--------------------------< O P E N L I B R A R Y >--------------------------------------------------------
Formats an OpenLibrary link, and checks for associated errors.
]]
local function openlibrary(id, access)
local code;
local handler = cfg.id_handlers['OL'];
local ident;
ident, code = id:match("^(%d+([AMW]))$"); -- optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W'; remove OL prefix
if not is_set (ident) then -- if malformed return an error
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access}) .. ' ' .. set_error( 'bad_ol' );
end
id = ident; -- use ident without the optional OL prefix (it has been removed)
if ( code == "A" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'authors/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
if ( code == "M" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'books/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
if ( code == "W" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'works/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
end
--[[--------------------------< P M C >------------------------------------------------------------------------
Format a PMC, do simple error checking, and check for embargoed articles.
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not
be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the
PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation
has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed ()
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.
PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.
]]
local function pmc(id, embargo)
local test_limit = 12000000; -- update this value as PMCs approach
local handler = cfg.id_handlers['PMC'];
local err_cat = ''; -- presume that PMC is valid
local id_num;
local text;
id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with pmc prefix
if is_set (id_num) then
add_maint_cat ('pmc_format');
else -- plain number without pmc prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber(id_num); -- convert id_num to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMC is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
else
id = tostring (id_num); -- make sure id is a string
end
else -- when id format incorrect
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
end
if is_set (embargo) then -- is PMC is still embargoed?
text = table.concat ( -- still embargoed so no external link
{
make_internal_link (handler.link, handler.label),
handler.separator,
id,
err_cat
});
else
text = external_link_id({link = handler.link, label = handler.label, q = handler.q, -- no embargo date or embargo has expired, ok to link to article
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
end
return text;
end
--[[--------------------------< P M I D >----------------------------------------------------------------------
Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable
test_limit will need to be updated periodically as more PMIDs are issued.
]]
local function pmid(id)
local test_limit = 40000000; -- update this value as PMIDs approach
local handler = cfg.id_handlers['PMID'];
local err_cat = ''; -- presume that PMID is valid
if id:match("[^%d]") then -- if PMID has anything but digits
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
else -- PMID is only digits
local id_num = tonumber(id); -- convert id to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMID is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
end
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< S 2 C I D >--------------------------------------------------------------------
Format an S2CID, do simple error checking
S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only
digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically
as more S2CIDs are issued.
]]
local function s2cid (id, access)
local test_limit = 300000000;
local handler = cfg.id_handlers['S2CID'];
local err_cat = ''; -- presume that S2CID is valid
local id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if test_limit < id_num then -- if S2CID is outside test limit boundaries
err_cat = ' ' .. set_error ('bad_s2cid'); -- set an error message
end
else -- when id format incorrect
err_cat = ' ' .. set_error ('bad_s2cid'); -- set an error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}) .. err_cat;
end
--[[--------------------------< S S R N >----------------------------------------------------------------------
Format an ssrn, do simple error checking
SSRNs are sequential numbers beginning at 100? and counting up. This code checks the ssrn to see that it is
only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need
to be updated periodically as more SSRNs are issued.
]]
local function ssrn (id)
local test_limit = 3500000; -- update this value as SSRNs approach
local handler = cfg.id_handlers['SSRN'];
local err_cat = ''; -- presume that SSRN is valid
local id_num;
local text;
id_num = id:match ('^%d+$'); -- id must be all digits
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber(id_num); -- convert id_num to a number for range testing
if 100 > id_num or test_limit < id_num then -- if SSRN is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_ssrn' ); -- set an error message
end
else -- when id format incorrect
err_cat = ' ' .. set_error( 'bad_ssrn' ); -- set an error message
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
return text;
end
--[[--------------------------< U S E N E T _ I D >------------------------------------------------------------
Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in
'<' and/or '>' angle brackets.
]]
local function usenet_id (id)
local handler = cfg.id_handlers['USENETID'];
local text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$')then -- doesn't have '@' or has one or first or last character is '< or '>'
text = text .. ' ' .. set_error( 'bad_message_id' ) -- add an error message if the message id is invalid
end
return text
end
--[[--------------------------< Z B L >-----------------------------------------------------------------------
A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional
]]
local function zbl (id)
local handler = cfg.id_handlers['ZBL'];
local err_cat = '';
id = id:gsub ('^[Zz][Bb][Ll]',""); -- identifier with zbl prefix; extract identifier
if (nil ~= id:match ("^%d%d%d%d%d%d%d%d$")) then
add_maint_cat ('zbl_format'); -- temporary
else
if (nil == id:match('^%d?%d?%d?%d%.%d%d%d%d%d$')) then -- id doesn't match the pattern
err_cat = ' ' .. set_error( 'bad_zbl' ); -- set an error message
end
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--============================<< I N T E R F A C E F U N C T I O N S >>==========================================
--[[--------------------------< B U I L D _ I D _ L I S T >--------------------------------------------------------
Takes a table of IDs created by extract_ids() and turns it into a table of formatted ID outputs.
inputs:
id_list – table of identifiers built by extract_ids()
options – table of various template parameter values used to modify some manually handled identifiers
]]
local function build_id_list( id_list, options )
local new_list, handler = {};
local function fallback(k) return { __index = function(t,i) return cfg.id_handlers[k][i] end } end;
for k, v in pairs( id_list ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
-- fallback to read-only cfg
handler = setmetatable( { ['id'] = v, ['access'] = options.IdAccessLevels[k] }, fallback(k) );
if handler.mode == 'external' then
table.insert( new_list, {handler.label, external_link_id( handler ) } );
elseif handler.mode == 'internal' then
table.insert( new_list, {handler.label, internal_link_id( handler ) } );
elseif handler.mode ~= 'manual' then
throw_error( 'unknown_ID_mode' );
elseif k == 'ARXIV' then
table.insert( new_list, {handler.label, arxiv( v, options.Class ) } );
elseif k == 'ASIN' then
table.insert( new_list, {handler.label, asin( v, options.ASINTLD ) } );
elseif k == 'BIBCODE' then
table.insert( new_list, {handler.label, bibcode( v, handler.access ) } );
elseif k == 'BIORXIV' then
table.insert( new_list, {handler.label, biorxiv( v ) } );
elseif k == 'CITESEERX' then
table.insert( new_list, {handler.label, citeseerx( v ) } );
elseif k == 'CNID' then
table.insert( new_list, {handler.label, cnid( v ) } );
elseif k == 'CSBN' then
table.insert( new_list, {handler.label, csbn( v ) } );
elseif k == 'DOI' then
table.insert( new_list, {handler.label, doi( v, options.DoiBroken, handler.access ) } );
elseif k == 'EISSN' then
table.insert( new_list, {handler.label, issn( v, true ) } ); -- true distinguishes eissn from issn
elseif k == 'HDL' then
table.insert( new_list, {handler.label, hdl( v, handler.access ) } );
elseif k == 'ISBN' then
local ISBN = internal_link_id( handler );
local check;
local err_type = '';
check, err_type = isbn( v );
if not check then
if is_set(options.IgnoreISBN) then -- ISBN is invalid; if |ignore-isbn-error= set
add_maint_cat ('ignore_isbn_err'); -- ad a maint category
else
ISBN = ISBN .. set_error( 'bad_isbn', {err_type}, false, " ", "" ); -- else display an error message
end
elseif is_set(options.IgnoreISBN) then -- ISBN is OK; if |ignore-isbn-error= set
add_maint_cat ('ignore_isbn_err'); -- because |ignore-isbn-error= unnecessary
end
table.insert( new_list, {handler.label, ISBN } );
elseif k == 'ISMN' then
table.insert( new_list, {handler.label, ismn( v ) } );
elseif k == 'ISSN' then
table.insert( new_list, {handler.label, issn( v ) } );
elseif k == 'JFM' then
table.insert( new_list, {handler.label, jfm( v ) } );
elseif k == 'LCCN' then
table.insert( new_list, {handler.label, lccn( v ) } );
elseif k == 'MR' then
table.insert( new_list, {handler.label, mr( v ) } );
elseif k == 'OCLC' then
table.insert( new_list, {handler.label, oclc( v ) } );
elseif k == 'OL' or k == 'OLA' then
table.insert( new_list, {handler.label, openlibrary( v, handler.access ) } );
elseif k == 'PMC' then
table.insert( new_list, {handler.label, pmc( v, options.Embargo ) } );
elseif k == 'PMID' then
table.insert( new_list, {handler.label, pmid( v ) } );
elseif k == 'S2CID' then
table.insert( new_list, {handler.label, s2cid( v, handler.access ) } );
elseif k == 'SSRN' then
table.insert( new_list, {handler.label, ssrn( v ) } );
elseif k == 'USENETID' then
table.insert( new_list, {handler.label, usenet_id( v ) } );
elseif k == 'ZBL' then
table.insert( new_list, {handler.label, zbl( v ) } );
else
throw_error( 'unknown_manual_ID' );
end
end
local function comp( a, b ) -- used in following table.sort()
return a[1] < b[1];
end
table.sort( new_list, comp );
for k, v in ipairs( new_list ) do
new_list[k] = v[2];
end
return new_list;
end
--[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for
any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to
the identifier list. Emits redundant error message is more than one alias exists in args
]]
local function extract_ids( args )
local id_list = {}; -- list of identifiers found in args
for k, v in pairs( cfg.id_handlers ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
v = select_one( args, v.parameters, 'redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present
if is_set(v) then id_list[k] = v; end -- if found in args, add identifier to our list
end
return id_list;
end
--[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >--------------------------------------
Fetches custom id access levels from arguments using configuration settings.
Parameters which have a predefined access level (e.g. arxiv) do not use this
function as they are directly rendered as free without using an additional parameter.
]]
local function extract_id_access_levels( args, id_list )
local id_accesses_list = {};
for k, v in pairs( cfg.id_handlers ) do
local access_param = v.custom_access;
local k_lower = string.lower(k);
if is_set(access_param) then
local access_level = args[access_param];
if is_set(access_level) then
if not in_array (access_level:lower(), cfg.keywords['id-access']) then
append_error( 'invalid_param_val', {access_param, access_level});
access_level = nil;
end
if not is_set(id_list[k]) then
append_error( 'param_access_requires_param', {k_lower});
end
if is_set(access_level) then
access_level = access_level:lower();
end
id_accesses_list[k] = access_level;
end
end
end
return id_accesses_list;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, error_page_ptr, links_page_ptr, validation_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
wrap_style = utilities_page_ptr.wrap_style;
append_error = error_page_ptr.append_error;
set_error = error_page_ptr.set_error;
throw_error = error_page_ptr.throw_error;
select_one = error_page_ptr.select_one;
add_maint_cat = error_page_ptr.add_maint_cat;
make_internal_link = links_page_ptr.make_internal_link;
is_valid_date_from_a_point = validation_page_ptr.is_valid_date_from_a_point;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
build_id_list = build_id_list,
extract_ids = extract_ids,
extract_id_access_levels = extract_id_access_levels,
is_embargoed = is_embargoed;
set_selected_modules = set_selected_modules;
}
b1d58a2f7f50e7581f1eb0fd0d2a6cf8012bb316
Module:Citation/CS1/Language
828
201
420
2023-08-20T14:31:25Z
zhwp>Xiplus
0
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, wrap_msg, wrap_style;
local add_prop_cat, add_maint_cat;
--[[--------------------------< L O C A L _ T A B L E >-------------------------------------------------------
]]
local local_table = {
['abe']= '西阿贝纳基语',
['abq']= '阿巴扎语',
['abq-latn']= '阿巴扎语(拉丁文字)',
['abs']= '安汶马来语',
['ady-cyrl']= '阿迪格语(西里尔文)',
['aeb-arab']= '突尼斯阿拉伯语(阿拉伯文字)',
['aeb-latn']= '突尼斯阿拉伯语(拉丁文字)',
['alc']= '阿拉卡卢夫语',
['ami']= '阿美语',
['azb']= '南阿塞拜疆语',
['bat-smg']= '萨莫吉希亚语',
['bbc-latn']= '多巴巴塔克语(拉丁文字)',
['bcc']= '南俾路支语',
['bcl']= '中比科尔语',
['bdr']= '西海岸巴瑶语',
['be-tarask']= '白俄罗斯语(传统正写法)',
['be-x-old']= '白俄罗斯语(传统正写法)',
['bgp']= '东俾路支语',
['bh']='博杰普尔语',
['bxr']='俄罗斯布里亚特语',
['cja']='西部占语',
['cja-arab']='西部占语(阿拉伯文字)',
['cja-cham']='西部占语(阿拉伯文字)',
['cja-latn']='西部占语(拉丁文字)',
['cjm']='东部占语',
['cjm-arab']='东部占语(阿拉伯文字)',
['cjm-cham']='东部占语(阿拉伯文字)',
['cjm-latn']='东部占语(拉丁文字)',
['cjy']='晋语',
['cjy-hans']='晋语(简体)',
['cjy-hant']='晋语(繁体)',
['ckt']='楚科奇语',
['en-in']= '印度英语',
['ike-cans']='东加拿大语(原住民音节)',
['ike-latn']='东加拿大语(拉丁文字)',
['ruq']='梅格莱诺-罗马尼亚语',
['ruq-cyrl']='梅格列诺-罗马尼亚语(西里尔文字)',
['ruq-grek']='梅格列诺-罗马尼亚语(希腊文字)',
['ruq-latn']='梅格列诺-罗马尼亚语(拉丁文字)',
['cdo']= '闽东语',
['cdo-hani']= '闽东语(汉字)',
['ja-hani'] = '日语(汉字文字)',
['ja-hira'] = '日语(平假名文字)',
['ja-hrkt'] = '日语(假名文字)',
['ja-kana'] = '日语(片假名文字)',
['ko-kp'] = '朝鲜朝鲜语',
['kk-cn'] = '中国哈萨克语',
['no'] = '挪威语',
['ojp'] = '古日语',
['ojp-hani'] = '古日语(汉字文字)',
['ojp-hira'] = '古日语(平假名文字)',
['tet'] = '德顿语',
['ug-arab'] = '维吾尔语(阿拉伯文字)',
['ug-latn'] = '维吾尔语(拉丁文字)',
-- ['zh-cn'] = '中国大陆中文',
-- ['zh-hans'] = '简体中文',
-- ['zh-hant'] = '繁體中文',
-- ['zh-hk'] = '香港中文',
['zh-min-nan'] = '闽南语',
-- ['zh-mo'] = '澳門中文',
-- ['zh-my'] = '马来西亚中文',
-- ['zh-sg'] = '新加坡中文',
-- ['zh-tw'] = '臺灣中文',
}
local function fetchLocalLanguageName (code)
return local_table[code];
end
--[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >----------------------------------------
|script-title= holds title parameters that are not written in Latin based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should
not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped
in italic markup.
Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate rtl languages from the English left to right.
|script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO639-1 language code and a colon:
|script-title=ja:*** *** (where * represents a Japanese character)
Spaces between the two-character code and the colon and the colon and the first script character are allowed:
|script-title=ja : *** ***
|script-title=ja: *** ***
|script-title=ja :*** ***
Spaces preceding the prefix are allowed: |script-title = ja:*** ***
The prefix is checked for validity. If it is a valid ISO639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can
know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute
is not added. At this time there is no error message for this condition.
Supports |script-title= and |script-chapter=
TODO: error messages when prefix is invalid ISO639-1 code; when script_value has prefix but no script;
]]
local function format_script_value (script_value)
local lang=''; -- initialize to empty string
local name;
if script_value:match('^%l%l%s*:') then -- if first 3 non-space characters are script language prefix
lang = script_value:match('^(%l%l)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script
if not is_set (lang) then
return ''; -- script_value was just the prefix so return empty string
end
-- if we get this far we have prefix and script
name = mw.language.fetchLanguageName( lang, mw.getContentLanguage():getCode() ); -- get language name so that we can use it to categorize
if is_set (name) then -- is prefix a proper ISO 639-1 language code?
script_value = script_value:gsub ('^%l%l%s*:%s*', ''); -- strip prefix from script
-- is prefix one of these language codes?
if in_array (lang, {'ar', 'bg', 'bs', 'dv', 'el', 'fa', 'he', 'hy', 'ja', 'ka', 'ko', 'ku', 'mk', 'ps', 'ru', 'sd', 'sr', 'th', 'uk', 'ug', 'yi', 'zh'}) then
add_prop_cat ('script_with_name', {name, lang})
else
add_prop_cat ('script')
end
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute
else
lang = ''; -- invalid so set lang to empty string
end
end
if is_set(script_value) then
script_value = '-{R|' .. script_value .. '}-';
end
script_value = wrap_style('bdi', {lang, script_value}); -- isolate in case script is rtl
return script_value;
end
--[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script value has been
wrapped in <bdi> tags.
]]
local function script_concatenate (title, script)
if is_set(title) then
title = '-{R|' .. title .. '}-';
end
if is_set (script) then
script = format_script_value (script); -- <bdi> tags, lang atribute, categorization, etc; returns empty string on error
if is_set (script) then
title = title .. ' ' .. script; -- concatenate title and script title
end
end
return title;
end
--[[--------------------------< G E T _ I S O 6 3 9 _ C O D E >------------------------------------------------
Validates language names provided in |language= parameter if not an ISO639-1 code. Handles the special case that is Norwegian where
ISO639-1 code 'no' is mapped to language name 'Norwegian Bokmål' by Extention:CLDR.
Returns the language name and associated ISO639-1 code. Because case of the source may be incorrect or different from the case that Wikimedia
uses, the name comparisons are done in lower case and when a match is found, the Wikimedia version (assumed to be correct) is returned along
with the code. When there is no match, we return the original language name string.
mw.language.fetchLanguageNames() will return a list of languages that aren't part of ISO639-1. Names that aren't ISO639-1 but that are included
in the list will be found if that name is provided in the |language= parameter. For example, if |language=Samaritan Aramaic, that name will be
found with the associated code 'sam', not an ISO639-1 code. When names are found and the associated code is not two characters, this function
returns only the Wikimedia language name.
Adapted from code taken from Module:Check ISO 639-1.
]]
local function get_iso639_code (lang)
if 'norwegian' == lang:lower() then -- special case related to Wikimedia remap of code 'no' at Extension:CLDR
return '挪威语', 'no'; -- Make sure rendered version is properly capitalized
end
local languages = mw.language.fetchLanguageNames (mw.getContentLanguage():getCode(), 'all') -- get a list of language names known to Wikimedia
-- ('all' is required for North Ndebele, South Ndebele, and Ojibwa)
local langlc = mw.ustring.lower (lang); -- lower case version for comparisons
for code, name in pairs (languages) do -- scan the list to see if we can find our language
if langlc == mw.ustring.lower (name) then
if 2 ~= code:len() then -- ISO639-1 codes only
return name; -- so return the name but not the code
end
return name, code; -- found it, return name to ensure proper capitalization and the ISO639-1 code
end
end
return lang; -- not valid language; return language in original case and nil for ISO639-1 code
end
--[[--------------------------< L A N G U A G E _ P A R A M E T E R >------------------------------------------
Get language name from ISO639-1 code value provided. If a code is valid use the returned name; if not, then use the value that was provided with the language parameter.
There is an exception. There are three ISO639-1 codes for Norewegian language variants. There are two official variants: Norwegian Bokmål (code 'nb') and
Norwegian Nynorsk (code 'nn'). The third, code 'no', is defined by ISO639-1 as 'Norwegian' though in Norway this is pretty much meaningless. However, it appears
that on enwiki, editors are for the most part unaware of the nb and nn variants (compare page counts for these variants at Category:Articles with non-English-language external links.
Because Norwegian Bokmål is the most common language variant, Media wiki has been modified to return Norwegian Bokmål for ISO639-1 code 'no'. Here we undo that and
return 'Norwegian' when editors use |language=no. We presume that editors don't know about the variants or can't descriminate between them.
See Help talk:Citation Style_1#An ISO 639-1 language name test
When |language= contains a valid ISO639-1 code, the page is assigned to the category for that code: Category:Norwegian-language sources (no) if
the page is a mainspace page and the ISO639-1 code is not 'en'. Similarly, if the parameter is |language=Norwegian, it will be categorized in the same way.
This function supports multiple languages in the form |language=nb, French, th where the language names or codes are separated from each other by commas.
]]
local function language_parameter (lang)
local code; -- the ISO639-1 two character code
local name; -- the language name
local language_list = {}; -- table of language names to be rendered
local names_table = {}; -- table made from the value assigned to |language=
if not is_set (lang) then
return '';
end
names_table = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list
for _, lang in ipairs (names_table) do -- reuse lang
name = fetchLocalLanguageName (lang:lower()); -- local table first
if not is_set (name) then
if lang:match ('^%a%a%-') or 2 == lang:len() then -- ISO639-1 language code are 2 characters (fetchLanguageName also supports 3 character codes)
if lang:match ('^zh-') then
name = mw.language.fetchLanguageName (lang:lower(), lang:lower());
else
if not is_set (name) then
name = mw.language.fetchLanguageName (lang:lower(), mw.getContentLanguage():getCode());
-- get ISO 639-1 language name if Language is a proper code
end
end
end
end
if is_set (name) then -- if Language specified a valid ISO639-1 code
code = lang:lower(); -- save it
else
name, code = get_iso639_code (lang); -- attempt to get code from name (assign name here so that we are sure of proper capitalization)
end
if is_set (code) then
if 'zh' ~= code and not code:match ('^zh-') then -- Chinese not the language
add_prop_cat ('foreign_lang_source', {name, code})
end
else
add_maint_cat ('unknown_lang'); -- add maint category if not already added
end
table.insert (language_list, name);
name = ''; -- so we can reuse it
end
code = #language_list -- reuse code as number of languages in the list
if 2 >= code then
name = table.concat (language_list, '及') -- insert '及' between two language names
elseif 2 < code then
language_list[code] = '及' .. language_list[code]; -- prepend last name with '及'
name = table.concat (language_list, '、'); -- and concatenate with '<comma><space>' separators
name = name:gsub ('、及', '及', 1);
end
return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)'
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
]]
local function set_selected_modules (utilities_page_ptr, error_page_ptr)
is_set = utilities_page_ptr.is_set; -- import functions from selected Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array;
wrap_style = utilities_page_ptr.wrap_style;
wrap_msg = utilities_page_ptr.wrap_msg;
add_prop_cat = error_page_ptr.add_prop_cat; -- import functions from selected Module:Citation/CS1/Error module
add_maint_cat = error_page_ptr.add_maint_cat;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
script_concatenate = script_concatenate,
language_parameter =language_parameter,
set_selected_modules = set_selected_modules
}
b9ee021194332f453ba7b48e49bd8e32553dc741
Template:Hlist/styles.css
10
90
174
2023-08-20T20:50:05Z
zhwp>Xiplus-abot
0
已更改“[[Template:Hlist/styles.css]]”的保护设置:高風險模板:256998引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
sanitized-css
text/css
.hlist ul,
.hlist ol {
padding-left: 0;
}
/* reset hlist margins of Minerva */
.hlist li,
.hlist dd,
.hlist dt {
margin: 0;
display: inline;
}
.hlist dt:after,
.hlist dd:after,
.hlist li:after {
white-space: normal;
}
/* Generate interpuncts */
.hlist dt:after {
content: " :";
}
.hlist dd:after,
.hlist li:after {
content: " · ";
font-weight: bold;
}
.hlist-pipe dd:after,
.hlist-pipe li:after {
content: " | ";
font-weight: normal;
}
.hlist-hyphen dd:after,
.hlist-hyphen li:after {
content: " - ";
font-weight: normal;
}
.hlist-comma dd:after,
.hlist-comma li:after {
content: "、";
font-weight: normal;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist dd:last-child:after,
.hlist dt:last-child:after,
.hlist li:last-child:after {
content: none;
}
/* Put ordinals in front of ordered list items */
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol {
counter-reset: listitem;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol > li {
counter-increment: listitem;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol > li:before {
content: " " counter(listitem) " ";
white-space: nowrap;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist dd ol > li:first-child:before,
.hlist dt ol > li:first-child:before,
.hlist li ol > li:first-child:before {
content: " (" counter(listitem) " ";
}
/* Put ordinals in front of ordered list items */
.hlist ol {
counter-reset: listitem;
}
.hlist ol > li {
counter-increment: listitem;
}
.hlist ol > li:before {
content: " " counter(listitem) "\a0";
}
.hlist dd ol > li:first-child:before,
.hlist dt ol > li:first-child:before,
.hlist li ol > li:first-child:before {
content: " (" counter(listitem) "\a0";
}
/* make an inline list with either comma or semicolon separators */
ul.cslist, ul.sslist {
margin: 0;
padding: 0;
display: inline-block;
list-style: none;
}
.cslist li, .sslist li {
margin: 0;
display: inline-block;
}
.cslist li:after {
content: ",";
}
.sslist li:after {
content: ";";
}
.cslist li:last-child:after, .sslist li:last-child:after {
content: none;
}
1cdc0ded2a44e617938a2368d34995a74727972a
Module:Navbar/configuration
828
121
236
2023-08-20T20:50:25Z
zhwp>Xiplus-abot
0
已更改“[[Module:Navbar/configuration]]”的保护设置:高風險模板:289210引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
return {
['templatestyles'] = 'Module:Navbar/styles.css',
['hlist_templatestyles'] = 'Hlist/styles.css',
['box_text'] = '本模板:', -- default text box when not plain or mini
['title_namespace'] = 'Template', -- namespace to default to for title
['invalid_title'] = '页面不存在 ',
['classes'] = { -- set a line to nil if you don't want it
['navbar'] = 'navbar',
['plainlinks'] = 'plainlinks', -- plainlinks
['horizontal_list'] = 'hlist', -- horizontal list class
['mini'] = 'navbar-mini', -- class indicating small links in the navbar
['this_box'] = 'navbar-boxtext',
['brackets'] = 'navbar-brackets',
-- 'collapsible' is the key for a class to indicate the navbar is
-- setting up the collapsible element in addition to the normal
-- navbar.
['collapsible'] = 'navbar-collapse',
['collapsible_title_mini'] = 'navbar-ct-mini',
['collapsible_title_full'] = 'navbar-ct-full'
}
}
eb732eb337355f0e1de8c27932d500f70419de87
那艺娜维基:Div col/styles.css
4
15
25
2023-09-24T17:28:06Z
zhwp>蕭漫
0
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
/* Unbulleted lists */
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
76c2c0a042b9164cff638cd44af5ab129702c141
Template:Div col/styles.css
10
39
73
2023-09-24T17:28:06Z
zhwp>蕭漫
0
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
/* Unbulleted lists */
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
76c2c0a042b9164cff638cd44af5ab129702c141
那艺娜维基:Div col
4
14
23
2023-09-24T19:26:50Z
zhwp>蕭漫
0
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{cols|{{{1|}}}}}}{{{colwidth|{{{2|}}}}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{cols|{{{1|}}}}}}|column-count:{{{cols|{{{1|}}}}}}; column-width:auto;<!-- 用以覆盖[[T:Div col/styles.css]]中预设的列宽“30em”,使列数不受其影响 -->}}{{#if:{{{colwidth|{{{2|}}}}}}|column-width:{{{colwidth|{{{2|}}}}}};}}{{#if:{{{gap|}}}|column-gap:{{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
--><!--{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}--><!--
--></includeonly><!--{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}--><noinclude>
{{Documentation}}
</noinclude>
b9f1dd532f74d3c57839cafc7017868d579f8880
Template:Div col
10
38
71
2023-09-24T19:26:50Z
zhwp>蕭漫
0
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{cols|{{{1|}}}}}}{{{colwidth|{{{2|}}}}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{cols|{{{1|}}}}}}|column-count:{{{cols|{{{1|}}}}}}; column-width:auto;<!-- 用以覆盖[[T:Div col/styles.css]]中预设的列宽“30em”,使列数不受其影响 -->}}{{#if:{{{colwidth|{{{2|}}}}}}|column-width:{{{colwidth|{{{2|}}}}}};}}{{#if:{{{gap|}}}|column-gap:{{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
--><!--{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}--><!--
--></includeonly><!--{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}--><noinclude>
{{Documentation}}
</noinclude>
b9f1dd532f74d3c57839cafc7017868d579f8880
Module:Effective protection expiry
828
110
214
2023-10-01T11:45:21Z
zhwp>Borschts
0
已从[[:en:Module:Effective_protection_expiry]]导入1个版本
Scribunto
text/plain
local p = {}
-- Returns the expiry of a restriction of an action on a given title, or unknown if it cannot be known.
-- If no title is specified, the title of the page being displayed is used.
function p._main(action, pagename)
local title
if type(pagename) == 'table' and pagename.prefixedText then
title = pagename
elseif pagename then
title = mw.title.new(pagename)
else
title = mw.title.getCurrentTitle()
end
pagename = title.prefixedText
if action == 'autoreview' then
local stabilitySettings = mw.ext.FlaggedRevs.getStabilitySettings(title)
return stabilitySettings and stabilitySettings.expiry or 'unknown'
elseif action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' then
error( 'First parameter must be one of edit, move, create, upload, autoreview', 2 )
end
local rawExpiry = mw.getCurrentFrame():callParserFunction('PROTECTIONEXPIRY', action, pagename)
if rawExpiry == 'infinity' then
return 'infinity'
elseif rawExpiry == '' then
return 'unknown'
else
local year, month, day, hour, minute, second = rawExpiry:match(
'^(%d%d%d%d)(%d%d)(%d%d)(%d%d)(%d%d)(%d%d)$'
)
if year then
return string.format(
'%s-%s-%sT%s:%s:%s',
year, month, day, hour, minute, second
)
else
error('internal error in Module:Effective protection expiry; malformed expiry timestamp')
end
end
end
setmetatable(p, { __index = function(t, k)
return function(frame)
return t._main(k, frame.args[1])
end
end })
return p
9a8c58dc2667232ed08a9b206a5d89ca8150312b
MediaWiki:Gadget-Twinkle.js
8
150
302
2023-11-06T13:15:36Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
/**
* vim: set noet sts=0 sw=8:
* +-------------------------------------------------------------------------+
* | === 警告:全局小工具文件 === |
* | 对此文件的修改会影响许多用户。 |
* | 修改前请联系维护者。 |
* +-------------------------------------------------------------------------+
*
* 从Github导入 [https://github.com/Xi-Plus/twinkle]
* 所有修改都應該在儲存庫中進行,否則將在下次更新時遺失。
*
* ----------
*
* 这是Xiplus版本的Twinkle,是新手、管理员及他们之间的用户的
* 好帮手。请参见[[WP:TW]]以获取更多信息。
*/
// <nowiki>
/* global Morebits */
(function (window, document, $) { // Wrap with anonymous function
// Check if account is experienced enough to use Twinkle
if (!Morebits.userIsInGroup('autoconfirmed') && !Morebits.userIsInGroup('confirmed')) {
return;
}
var Twinkle = {};
window.Twinkle = Twinkle; // allow global access
var conv = require('ext.gadget.HanAssist').conv;
/**
* Twinkle-specific data shared by multiple modules
* Likely customized per installation
*/
// Custom change tag(s) to be applied to all Twinkle actions, create at Special:Tags
Twinkle.changeTags = 'Twinkle';
// Available for actions that don't (yet) support tags
// currently: FlaggedRevs and PageTriage
Twinkle.summaryAd = ' ([[WP:TW|TW]])';
// Various hatnote templates, used when tagging (csd/xfd/tag/prod/protect) to ensure [[w:en:MOS:ORDER]]
Twinkle.hatnoteRegex = '(?:Short[ _]description)|(?:Rellink|Hatnote|HAT)|(?:Main|细节|細節|Main[ _]articles|主条目|主條目|Hurricane[ _]main|条目|條目|主|頁面|页面|主頁面|主页面|主頁|主页|主題目|主题目|Main[ _]article|AP)|(?:Wrongtitle|Correct[ _]title)|(?:主条目消歧义|主條目消歧義|消歧义链接|消歧義鏈接|消歧義連結|消连|消連|消歧义连结|DisambLink|Noteref|Dablink)|(?:Distinguish|不是|Not|提示|混淆|分別|分别|區別|区别|本条目的主题不是|本條目的主題不是|本条目主题不是|本條目主題不是|条目主题不是|條目主題不是|主题不是|主題不是|Confused|区分|區分|Confusion|Confuse|RedirectNOT|Misspelling)|(?:Distinguish2|SelfDistinguish|Not2|不是2)|(?:For)|(?:Details|Further|See|另见|另見|More|相關條目|相关条目|Detail|见|見|更多资料|更多資料|Further[ _]information|更多资讯|更多資訊|More[ _]information|更多信息)|(?:Selfref)|(?:About|Otheruses4|关于|關於)|(?:Other[ _]uses|Otheruse|条目消歧义|條目消歧義|他用|Otheruses)|(?:Other[ _]uses list|Otheruselist|主條目消歧義列表|主条目消歧义列表|Otheruseslist|Aboutlist|About[ _]list|Otheruses[ _]list)|(?:Redirect|重定向至此|Redirects[ _]here|Redirect[ _]to)|(?:Redirect2|主條目消歧義2|主条目消歧义2|Redir|重定向至此2)|(?:Redirect3)|(?:Redirect4)|(?:Redirect-distinguish)|(?:Redirect-synonym)|(?:Redirect-multi)|(?:See[ _]Wiktionary|Seewikt)|(?:Seealso|参看|參看|See[ _]also|参见|參見|Also)|(?:See[ _]also2|Seealso2|不轉換參見|不转换参见)|(?:Other[ _]places)|(?:Contrast|對比|对比)';
Twinkle.initCallbacks = [];
/**
* Adds a callback to execute when Twinkle has loaded.
* @param {function} func
* @param {string} [name] - name of module used to check if is disabled.
* If name is not given, module is loaded unconditionally.
*/
Twinkle.addInitCallback = function twinkleAddInitCallback(func, name) {
Twinkle.initCallbacks.push({ func: func, name: name });
};
Twinkle.defaultConfig = {};
/**
* This holds the default set of preferences used by Twinkle.
* It is important that all new preferences added here, especially admin-only ones, are also added to
* |Twinkle.config.sections| in twinkleconfig.js, so they are configurable via the Twinkle preferences panel.
* For help on the actual preferences, see the comments in twinkleconfig.js.
*
* Formerly Twinkle.defaultConfig.twinkle and Twinkle.defaultConfig.friendly
*/
Twinkle.defaultConfig = {
// General
userTalkPageMode: 'tab',
dialogLargeFont: false,
disabledModules: Morebits.userIsSysop ? [] : ['block'], // default to disable block for non-sysop, if enable manually, they can only use it to tag userpage
disabledSysopModules: [],
// ARV
spiWatchReport: 'yes',
// Block
defaultToBlock64: false,
defaultToPartialBlocks: false,
blankTalkpageOnIndefBlock: false,
watchBlockNotices: 'yes',
customBlockReasonList: [],
// Fluff (revert and rollback)
openTalkPage: [ ],
openTalkPageOnAutoRevert: false,
rollbackInPlace: false,
markRevertedPagesAsMinor: [ 'vand' ],
watchRevertedPages: [ 'agf', 'norm', 'vand', 'torev' ],
watchRevertedExpiry: 'yes',
offerReasonOnNormalRevert: true,
confirmOnFluff: false,
confirmOnMobileFluff: true,
showRollbackLinks: [ 'diff', 'others' ],
customRevertSummary: [],
// DI (twinkleimage)
notifyUserOnDeli: true,
deliWatchPage: 'default',
deliWatchUser: 'default',
// Protect
watchRequestedPages: 'yes',
watchPPTaggedPages: 'default',
watchProtectedPages: 'default',
// CSD
speedySelectionStyle: 'buttonClick',
watchSpeedyPages: [ ],
watchSpeedyExpiry: 'yes',
markSpeedyPagesAsPatrolled: true,
// these next two should probably be identical by default
notifyUserOnSpeedyDeletionNomination: [ 'db', 'g1', 'g2', 'g3', 'g5', 'g11', 'g12', 'g13', 'g16', 'a1', 'a2', 'a5', 'a6', 'o7', 'o8', 'f6', 'r2', 'r3', 'r7' ],
welcomeUserOnSpeedyDeletionNotification: [ 'db', 'g1', 'g2', 'g3', 'g5', 'g11', 'g12', 'g13', 'g16', 'a1', 'a2', 'a5', 'a6', 'o7', 'o8', 'f6', 'r2', 'r3', 'r7' ],
promptForSpeedyDeletionSummary: [],
openUserTalkPageOnSpeedyDelete: [ ],
deleteTalkPageOnDelete: true,
deleteRedirectsOnDelete: true,
deleteSysopDefaultToDelete: false,
speedyWindowHeight: 500,
speedyWindowWidth: 800,
logSpeedyNominations: false,
speedyLogPageName: 'CSD日志',
noLogOnSpeedyNomination: [ 'o1' ],
enlargeG11Input: false,
// Unlink
unlinkNamespaces: [ '0', '10', '100', '102', '118' ],
// Warn
defaultWarningGroup: '1',
combinedSingletMenus: false,
showSharedIPNotice: true,
watchWarnings: 'yes',
oldSelect: false,
customWarningList: [],
autoMenuAfterRollback: false,
// XfD
logXfdNominations: false,
xfdLogPageName: 'AFD日志',
noLogOnXfdNomination: [],
xfdWatchDiscussion: 'default',
xfdWatchPage: 'default',
xfdWatchUser: 'default',
markXfdPagesAsPatrolled: true,
FwdCsdToXfd: Morebits.userIsSysop,
afdDefaultCategory: 'delete',
afdFameDefaultReason: '沒有足夠的可靠資料來源能夠讓這個條目符合[[Wikipedia:關注度]]中的標準',
afdSubstubDefaultReason: '過期小小作品',
XfdClose: Morebits.userIsSysop ? 'all' : 'hide',
// Copyvio
copyvioWatchPage: 'yes',
copyvioWatchUser: 'yes',
markCopyvioPagesAsPatrolled: true,
// Hidden preferences
autolevelStaleDays: 3,
revertMaxRevisions: 50, // intentionally limited
batchMax: 5000,
batchChunks: 50,
configPage: 'Wikipedia:Twinkle/参数设置',
projectNamespaceName: mw.config.get('wgFormattedNamespaces')[4],
sandboxPage: 'Wikipedia:沙盒',
// Deprecated options, as a fallback for add-on scripts/modules
summaryAd: ' ([[WP:TW|TW]])',
deletionSummaryAd: ' ([[WP:TW|TW]])',
protectionSummaryAd: ' ([[WP:TW|TW]])',
blockSummaryAd: ' ([[WP:TW|TW]])',
// Formerly defaultConfig.friendly:
// Tag
groupByDefault: true,
watchTaggedPages: 'yes',
watchMergeDiscussions: 'yes',
markTaggedPagesAsMinor: false,
markTaggedPagesAsPatrolled: true,
tagArticleSortOrder: 'cat',
customTagList: [],
customFileTagList: [],
customRedirectTagList: [],
// Stub
watchStubbedPages: false,
markStubbedPagesAsMinor: false,
markStubbedPagesAsPatrolled: true,
stubArticleSortOrder: 'cat',
customStubList: [],
// Welcome
topWelcomes: false,
watchWelcomes: 'yes',
welcomeHeading: conv({ hans: '欢迎', hant: '歡迎' }),
insertHeadings: true,
insertUsername: true,
insertSignature: true, // sign welcome templates, where appropriate
quickWelcomeMode: 'norm',
quickWelcomeTemplate: 'Welcome',
customWelcomeList: [],
customWelcomeSignature: true,
// Talkback
markTalkbackAsMinor: true,
insertTalkbackSignature: true, // always sign talkback templates
talkbackHeading: conv({ hans: '回复通告', hant: '回覆通告' }),
mailHeading: conv({ hans: '您有新邮件!', hant: '您有新郵件!' }),
// Shared
markSharedIPAsMinor: true
};
// now some skin dependent config.
switch (mw.config.get('skin')) {
case 'vector':
case 'vector-2022':
Twinkle.defaultConfig.portletArea = 'right-navigation';
Twinkle.defaultConfig.portletId = 'p-twinkle';
Twinkle.defaultConfig.portletName = 'TW';
Twinkle.defaultConfig.portletType = 'menu';
Twinkle.defaultConfig.portletNext = 'p-search';
break;
case 'timeless':
Twinkle.defaultConfig.portletArea = '#page-tools .sidebar-inner';
Twinkle.defaultConfig.portletId = 'p-twinkle';
Twinkle.defaultConfig.portletName = 'Twinkle';
Twinkle.defaultConfig.portletType = null;
Twinkle.defaultConfig.portletNext = 'p-userpagetools';
break;
default:
Twinkle.defaultConfig.portletArea = null;
Twinkle.defaultConfig.portletId = 'p-cactions';
Twinkle.defaultConfig.portletName = null;
Twinkle.defaultConfig.portletType = null;
Twinkle.defaultConfig.portletNext = null;
}
Twinkle.getPref = function twinkleGetPref(name) {
if (typeof Twinkle.prefs === 'object' && Twinkle.prefs[name] !== undefined) {
return Twinkle.prefs[name];
}
// Old preferences format, used before twinkleoptions.js was a thing
if (typeof window.TwinkleConfig === 'object' && window.TwinkleConfig[name] !== undefined) {
return window.TwinkleConfig[name];
}
if (typeof window.FriendlyConfig === 'object' && window.FriendlyConfig[name] !== undefined) {
return window.FriendlyConfig[name];
}
return Twinkle.defaultConfig[name];
};
/**
* **************** Twinkle.addPortlet() ****************
*
* Adds a portlet menu to one of the navigation areas on the page.
* This is necessarily quite a hack since skins, navigation areas, and
* portlet menu types all work slightly different.
*
* Available navigation areas depend on the skin used.
* Vector:
* For each option, the outer nav class contains "vector-menu", the inner div class is "vector-menu-content", and the ul is "vector-menu-content-list"
* "mw-panel", outer nav class contains "vector-menu-portal". Existing portlets/elements: "p-logo", "p-navigation", "p-interaction", "p-tb", "p-coll-print_export"
* "left-navigation", outer nav class contains "vector-menu-tabs" or "vector-menu-dropdown". Existing portlets: "p-namespaces", "p-variants" (menu)
* "right-navigation", outer nav class contains "vector-menu-tabs" or "vector-menu-dropdown". Existing portlets: "p-views", "p-cactions" (menu), "p-search"
* Special layout of p-personal portlet (part of "head") through specialized styles.
* Monobook:
* "column-one", outer nav class "portlet", inner div class "pBody". Existing portlets: "p-cactions", "p-personal", "p-logo", "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
* Special layout of p-cactions and p-personal through specialized styles.
* Modern:
* "mw_contentwrapper" (top nav), outer nav class "portlet", inner div class "pBody". Existing portlets or elements: "p-cactions", "mw_content"
* "mw_portlets" (sidebar), outer nav class "portlet", inner div class "pBody". Existing portlets: "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
*
* @param String navigation -- id of the target navigation area (skin dependant, on vector either of "left-navigation", "right-navigation", or "mw-panel")
* @param String id -- id of the portlet menu to create, preferably start with "p-".
* @param String text -- name of the portlet menu to create. Visibility depends on the class used.
* @param String type -- type of portlet. Currently only used for the vector non-sidebar portlets, pass "menu" to make this portlet a drop down menu.
* @param Node nextnodeid -- the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end.
*
* @return Node -- the DOM node of the new item (a DIV element) or null
*/
Twinkle.addPortlet = function(navigation, id, text, type, nextnodeid) {
// sanity checks, and get required DOM nodes
var root = document.getElementById(navigation) || document.querySelector(navigation);
if (!root) {
return null;
}
var item = document.getElementById(id);
if (item) {
if (item.parentNode && item.parentNode === root) {
return item;
}
return null;
}
var nextnode;
if (nextnodeid) {
nextnode = document.getElementById(nextnodeid);
}
// verify/normalize input
var skin = mw.config.get('skin');
if ((skin !== 'vector' && skin !== 'vector-2022') || (navigation !== 'left-navigation' && navigation !== 'right-navigation')) {
type = null; // menu supported only in vector's #left-navigation & #right-navigation
}
var outerNavClass, innerDivClass;
switch (skin) {
case 'vector':
case 'vector-2022':
// XXX: portal doesn't work
if (navigation !== 'portal' && navigation !== 'left-navigation' && navigation !== 'right-navigation') {
navigation = 'mw-panel';
}
outerNavClass = 'mw-portlet vector-menu';
if (navigation === 'mw-panel') {
outerNavClass += ' vector-menu-portal';
} else if (type === 'menu') {
outerNavClass += ' vector-menu-dropdown vector-dropdown vector-menu-dropdown-noicon';
} else {
outerNavClass += ' vector-menu-tabs';
}
innerDivClass = 'vector-menu-content vector-dropdown-content';
break;
case 'modern':
if (navigation !== 'mw_portlets' && navigation !== 'mw_contentwrapper') {
navigation = 'mw_portlets';
}
outerNavClass = 'portlet';
break;
case 'timeless':
outerNavClass = 'mw-portlet';
innerDivClass = 'mw-portlet-body';
break;
default:
navigation = 'column-one';
outerNavClass = 'portlet';
break;
}
// Build the DOM elements.
var outerNav, heading;
if (skin === 'vector-2022') {
outerNav = document.createElement('div');
heading = document.createElement('label');
} else {
outerNav = document.createElement('nav');
heading = document.createElement('h3');
}
outerNav.setAttribute('aria-labelledby', id + '-label');
// Vector getting vector-menu-empty FIXME TODO
outerNav.className = outerNavClass + ' emptyPortlet';
outerNav.id = id;
if (nextnode && nextnode.parentNode === root) {
root.insertBefore(outerNav, nextnode);
} else {
root.appendChild(outerNav);
}
heading.id = id + '-label';
var ul = document.createElement('ul');
if (skin === 'vector' || skin === 'vector-2022') {
heading.setAttribute('for', id + '-dropdown-checkbox');
ul.className = 'vector-menu-content-list';
heading.className = 'vector-menu-heading vector-dropdown-label';
// add invisible checkbox to keep menu open when clicked
// similar to the p-cactions ("More") menu
if (outerNavClass.indexOf('vector-menu-dropdown') !== -1) {
var chkbox = document.createElement('input');
chkbox.id = id + '-dropdown-checkbox';
chkbox.className = 'vector-menu-checkbox vector-dropdown-checkbox';
chkbox.setAttribute('type', 'checkbox');
chkbox.setAttribute('aria-labelledby', id + '-label');
outerNav.appendChild(chkbox);
// Vector gets its title in a span; all others except
// timeless have no title, and it has no span
var span = document.createElement('span');
span.appendChild(document.createTextNode(text));
heading.appendChild(span);
var a = document.createElement('a');
a.href = '#';
$(a).click(function(e) {
e.preventDefault();
});
heading.appendChild(a);
}
} else {
// Basically just Timeless
heading.appendChild(document.createTextNode(text));
}
outerNav.appendChild(heading);
if (innerDivClass) {
var innerDiv = document.createElement('div');
innerDiv.className = innerDivClass;
innerDiv.appendChild(ul);
outerNav.appendChild(innerDiv);
} else {
outerNav.appendChild(ul);
}
return outerNav;
};
/**
* **************** Twinkle.addPortletLink() ****************
* Builds a portlet menu if it doesn't exist yet, and add the portlet link.
* @param task: Either a URL for the portlet link or a function to execute.
*/
Twinkle.addPortletLink = function(task, text, id, tooltip) {
if (Twinkle.getPref('portletArea') !== null) {
Twinkle.addPortlet(Twinkle.getPref('portletArea'), Twinkle.getPref('portletId'), Twinkle.getPref('portletName'), Twinkle.getPref('portletType'), Twinkle.getPref('portletNext'));
}
var link = mw.util.addPortletLink(Twinkle.getPref('portletId'), typeof task === 'string' ? task : '#', text, id, tooltip);
$('.client-js .skin-vector #p-cactions').css('margin-right', 'initial');
if (typeof task === 'function') {
$(link).find('a').on('click', function (ev) {
task();
ev.preventDefault();
});
}
if ($.collapsibleTabs) {
$.collapsibleTabs.handleResize();
}
return link;
};
/**
* **************** General initialization code ****************
*/
var scriptpathbefore = mw.util.wikiScript('index') + '?title=',
scriptpathafter = '&action=raw&ctype=text/javascript&happy=yes';
// Retrieve the user's Twinkle preferences
$.ajax({
url: scriptpathbefore + 'User:' + encodeURIComponent(mw.config.get('wgUserName')) + '/twinkleoptions.js' + scriptpathafter,
dataType: 'text'
})
.fail(function () {
mw.notify(conv({ hans: '未能加载您的Twinkle参数设置', hant: '未能載入您的Twinkle偏好設定' }), { type: 'error' });
})
.done(function (optionsText) {
// Quick pass if user has no options
if (optionsText === '') {
return;
}
// Twinkle options are basically a JSON object with some comments. Strip those:
optionsText = optionsText.replace(/(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, '');
// First version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.
if (optionsText.lastIndexOf('window.Twinkle.prefs = ', 0) === 0) {
optionsText = optionsText.replace(/(?:^window.Twinkle.prefs = |;\n*$)/g, '');
}
try {
var options = JSON.parse(optionsText);
if (options) {
if (options.twinkle || options.friendly) { // Old preferences format
Twinkle.prefs = $.extend(options.twinkle, options.friendly);
} else {
Twinkle.prefs = options;
}
// v2 established after unification of Twinkle/Friendly objects
Twinkle.prefs.optionsVersion = Twinkle.prefs.optionsVersion || 1;
}
} catch (e) {
mw.notify(conv({ hans: '未能解析您的Twinkle参数设置', hant: '未能解析您的Twinkle偏好設定' }), { type: 'error' });
}
})
.always(function () {
$(Twinkle.load);
});
// Developers: you can import custom Twinkle modules here
// For example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);
Twinkle.load = function () {
// Don't activate on special pages other than those listed here, so
// that others load faster, especially the watchlist.
var activeSpecialPageList = [ 'Block', 'Contributions', 'AbuseLog', 'Recentchanges', 'Recentchangeslinked' ]; // wgRelevantUserName defined for non-sysops on Special:Block
if (Morebits.userIsSysop) {
activeSpecialPageList = activeSpecialPageList.concat([ 'DeletedContributions', 'Prefixindex', 'BrokenRedirects' ]);
}
if (mw.config.get('wgNamespaceNumber') === -1 &&
activeSpecialPageList.indexOf(mw.config.get('wgCanonicalSpecialPageName')) === -1) {
return;
}
// Prevent clickjacking
if (window.top !== window.self) {
return;
}
// Set custom Api-User-Agent header, for server-side logging purposes
Morebits.wiki.api.setApiUserAgent('Twinkle~zh (' + mw.config.get('wgWikiID') + ')');
Twinkle.disabledModules = Twinkle.getPref('disabledModules').concat(Twinkle.getPref('disabledSysopModules'));
// Redefine addInitCallback so that any modules being loaded now on are directly
// initialised rather than added to initCallbacks array
Twinkle.addInitCallback = function(func, name) {
if (!name || Twinkle.disabledModules.indexOf(name) === -1) {
func();
}
};
// Initialise modules that were saved in initCallbacks array
Twinkle.initCallbacks.forEach(function(module) {
Twinkle.addInitCallback(module.func, module.name);
});
// Increases text size in Twinkle dialogs, if so configured
if (Twinkle.getPref('dialogLargeFont')) {
mw.util.addCSS('.morebits-dialog-content, .morebits-dialog-footerlinks { font-size: 100% !important; } ' +
'.morebits-dialog input, .morebits-dialog select, .morebits-dialog-content button { font-size: inherit !important; }');
}
// Hide the lingering space if the TW menu is empty
var isVector = mw.config.get('skin') === 'vector' || mw.config.get('skin') === 'vector-2022';
if (isVector && Twinkle.getPref('portletType') === 'menu' && $('#p-twinkle').length === 0) {
$('#p-cactions').css('margin-right', 'initial');
}
};
/** Twinkle-specific utility functions shared by multiple modules */
// Used in batch, unlink, and deprod to sort pages by namespace, as
// json formatversion=2 sorts by pageid instead (#1251)
Twinkle.sortByNamespace = function(first, second) {
return first.ns - second.ns || (first.title > second.title ? 1 : -1);
};
// Used in deprod and unlink listings to link the page title
Twinkle.generateBatchPageLinks = function (checkbox) {
var $checkbox = $(checkbox);
var link = Morebits.htmlNode('a', $checkbox.val());
link.setAttribute('class', 'tw-batchpage-link');
link.setAttribute('href', mw.util.getUrl($checkbox.val()));
link.setAttribute('target', '_blank');
$checkbox.next().prepend([link, ' ']);
};
}(window, document, jQuery)); // End wrap with anonymous function
// </nowiki>
9317c10b81f37e8b15255a97a8890a101b63c23e
MediaWiki:Gadget-twinkleconfig.js
8
169
340
2023-11-06T13:17:01Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleconfig.js: Preferences module
****************************************
* Mode of invocation: Adds configuration form to Wikipedia:Twinkle/Preferences,
and adds an ad box to the top of user subpages belonging to the
currently logged-in user which end in '.js'
* Active on: What I just said. Yeah.
I, [[User:This, that and the other]], originally wrote this. If the code is misbehaving, or you have any
questions, don't hesitate to ask me. (This doesn't at all imply [[WP:OWN]]ership - it's just meant to
point you in the right direction.) -- TTO
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.config = {};
Twinkle.config.watchlistEnums = {
'yes': conv({ hans: '永久加入到监视列表', hant: '永久加入到監視清單' }),
'no': conv({ hans: '不加入到监视列表', hant: '不加入到監視清單' }),
'default': conv({ hans: '遵守站点设置', hant: '遵守站點設定' }),
'1 week': conv({ hans: '加入到监视列表1周', hant: '加入到監視清單1週' }),
'1 month': conv({ hans: '加入到监视列表1个月', hant: '加入到監視清單1個月' }),
'3 months': conv({ hans: '加入到监视列表3个月', hant: '加入到監視清單3個月' }),
'6 months': conv({ hans: '加入到监视列表6个月', hant: '加入到監視清單6個月' })
};
Twinkle.config.commonSets = {
csdCriteria: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdCriteriaDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
csdCriteriaNotification: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdCriteriaNotificationDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
csdAndDICriteria: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdAndDICriteriaDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
xfdCriteria: {
delete: conv({ hans: '删除', hant: '刪除' }), merge: conv({ hans: '合并', hant: '合併' }),
vmd: conv({ hans: '移动到维基词典', hant: '移動到維基詞典' }), vms: conv({ hans: '移动到维基文库', hant: '移動到維基文庫' }), vmb: conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' }), vmq: conv({ hans: '移动到维基语录', hant: '移動到維基語錄' }), vmvoy: conv({ hans: '移动到维基导游', hant: '移動到維基導遊' }), vmv: conv({ hans: '移动到维基学院', hant: '移動到維基學院' }),
fwdcsd: conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' }),
fame: conv({ hans: '批量关注度提删', hant: '批次關注度提刪' }), substub: conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' }), batch: conv({ hans: '批量其他提删', hant: '批次其他提刪' }),
ffd: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' })
},
xfdCriteriaDisplayOrder: [
'delete', 'merge',
'vmd', 'vms', 'vmb', 'vmq', 'vmvoy', 'vmv',
'fwdcsd',
'fame', 'substub', 'batch',
'ffd'
],
namespacesNoSpecial: {
0: conv({ hans: '(条目)', hant: '(條目)' }),
1: 'Talk',
2: 'User',
3: 'User talk',
4: 'Wikipedia',
5: 'Wikipedia talk',
6: 'File',
7: 'File talk',
8: 'MediaWiki',
9: 'MediaWiki talk',
10: 'Template',
11: 'Template talk',
12: 'Help',
13: 'Help talk',
14: 'Category',
15: 'Category talk',
100: 'Portal',
101: 'Portal talk',
102: 'WikiProject',
103: 'WikiProject talk',
118: 'Draft',
119: 'Draft talk',
828: 'Module',
829: 'Module talk'
}
};
/**
* Section entry format:
*
* {
* title: <human-readable section title>,
* module: <name of the associated module, used to link to sections>,
* adminOnly: <true for admin-only sections>,
* hidden: <true for advanced preferences that rarely need to be changed - they can still be modified by manually editing twinkleoptions.js>,
* preferences: [
* {
* name: <TwinkleConfig property name>,
* label: <human-readable short description - used as a form label>,
* helptip: <(optional) human-readable text (using valid HTML) that complements the description, like limits, warnings, etc.>
* adminOnly: <true for admin-only preferences>,
* type: <string|boolean|integer|enum|set|customList> (customList stores an array of JSON objects { value, label }),
* enumValues: <for type = "enum": a JSON object where the keys are the internal names and the values are human-readable strings>,
* setValues: <for type = "set": a JSON object where the keys are the internal names and the values are human-readable strings>,
* setDisplayOrder: <(optional) for type = "set": an array containing the keys of setValues (as strings) in the order that they are displayed>,
* customListValueTitle: <for type = "customList": the heading for the left "value" column in the custom list editor>,
* customListLabelTitle: <for type = "customList": the heading for the right "label" column in the custom list editor>
* },
* . . .
* ]
* },
* . . .
*
*/
Twinkle.config.sections = [
{
title: conv({ hans: '常规', hant: '常規' }),
module: 'general',
preferences: [
// TwinkleConfig.userTalkPageMode may take arguments:
// 'window': open a new window, remember the opened window
// 'tab': opens in a new tab, if possible.
// 'blank': force open in a new window, even if such a window exists
{
name: 'userTalkPageMode',
label: conv({ hans: '当要打开用户讨论页时', hant: '當要打開使用者討論頁時' }),
type: 'enum',
enumValues: {
window: conv({ hans: '在窗口中,替换成其它用户对话页', hant: '在當前分頁,替換成其它用戶討論頁' }),
tab: conv({ hans: '在新标签页中', hant: '在新分頁中' }),
blank: conv({ hans: '在全新的窗口中', hant: '在新視窗中' })
}
},
// TwinkleConfig.dialogLargeFont (boolean)
{
name: 'dialogLargeFont',
label: conv({ hans: '在Twinkle对话框中使用大号字体', hant: '在Twinkle對話方塊中使用大號字型' }),
type: 'boolean'
},
// Twinkle.config.disabledModules (array)
{
name: 'disabledModules',
label: conv({ hans: '关闭指定的Twinkle模块', hant: '關閉指定的Twinkle模組' }),
helptip: conv({ hans: '您在此选择的功能将无法使用,取消选择以重新启用功能。', hant: '您在此選擇的功能將無法使用,取消選擇以重新啟用功能。' }),
type: 'set',
setValues: { arv: conv({ hans: '告状', hant: '告狀' }), warn: '警告', block: conv({ hans: '封禁', hant: '封鎖' }), welcome: conv({ hans: '欢迎', hant: '歡迎' }), talkback: '通告', speedy: conv({ hans: '速删', hant: '速刪' }), copyvio: conv({ hans: '侵权', hant: '侵權' }), xfd: conv({ hans: '提删', hant: '提刪' }), image: conv({ hans: '图权', hant: '圖權' }), protect: conv({ hans: '保护', hant: '保護' }), tag: conv({ hans: '标记', hant: '標記' }), stub: '小作品', diff: conv({ hans: '差异', hant: '差異' }), unlink: conv({ hans: '链入', hant: '連入' }), fluff: '回退' }
},
// Twinkle.config.disabledSysopModules (array)
{
name: 'disabledSysopModules',
label: conv({ hans: '关闭指定的Twinkle管理员模块', hant: '關閉指定的Twinkle管理員模組' }),
helptip: conv({ hans: '您在此选择的功能将无法使用,取消选择以重新启用功能。', hant: '您在此選擇的功能將無法使用,取消選擇以重新啟用功能。' }),
adminOnly: true,
type: 'set',
setValues: { batchdelete: conv({ hans: '批删', hant: '批刪' }), batchundelete: conv({ hans: '批复', hant: '批復' }) }
}
]
},
{
title: conv({ hans: '告状', hant: '告狀' }),
module: 'arv',
preferences: [
{
name: 'spiWatchReport',
label: conv({ hans: '发起傀儡调查时加入到监视列表', hant: '發起傀儡調查時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: conv({ hans: '封禁用户', hant: '封鎖使用者' }),
module: 'block',
adminOnly: true,
preferences: [
// TwinkleConfig.defaultToBlock64 (boolean)
// Whether to default to just blocking the /64 on or off
{
name: 'defaultToBlock64',
label: conv({ hans: '对于IPv6地址,默认选择封禁/64段', hant: '對於IPv6地址,預設選擇封鎖/64段' }),
type: 'boolean'
},
// TwinkleConfig.defaultToPartialBlocks (boolean)
// Whether to default partial blocks on or off
{
name: 'defaultToPartialBlocks',
label: conv({ hans: '打开封禁菜单时默认选择部分封禁', hant: '打開封鎖選單時預設選擇部分封鎖' }),
type: 'boolean'
},
// TwinkleConfig.watchBlockNotices (string)
// Watchlist setting for the page which has been dispatched an warning or notice
{
name: 'watchBlockNotices',
label: conv({ hans: '发送封禁模板时加入用户讨论页到监视列表', hant: '發送封鎖模板時加入使用者討論頁到監視清單' }),
helptip: conv({ hans: '注意:如果对方使用Flow,对应讨论串总会加到监视列表中。', hant: '注意:如果對方使用Flow,對應討論串總會加到監視清單中。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'customBlockReasonList',
label: conv({ hans: '自定义封禁理由', hant: '自訂封鎖理由' }),
helptip: conv({ hans: '您可以加入常用的封禁理由。自定义的封禁理由会出现在一般的封禁理由下方。', hant: '您可以加入常用的封鎖理由。自訂的封鎖理由會出現在一般的封鎖理由下方。' }),
type: 'customList',
customListValueTitle: conv({ hans: '使用封禁模板(默认为 uw-block1)', hant: '使用封鎖模板(預設為 uw-block1)' }),
customListLabelTitle: conv({ hans: '“由于…您已被封禁”及封禁日志理由', hant: '「由於…您已被封鎖」及封鎖日誌理由' })
}
]
},
{
title: conv({ hans: '图片删除', hant: '圖片刪除' }),
module: 'image',
preferences: [
// TwinkleConfig.notifyUserOnDeli (boolean)
// If the user should be notified after placing a file deletion tag
{
name: 'notifyUserOnDeli',
label: conv({ hans: '默认勾选“通知创建者”', hant: '預設勾選「通知建立者」' }),
type: 'boolean'
},
// TwinkleConfig.deliWatchPage (string)
// The watchlist setting of the page tagged for deletion.
{
name: 'deliWatchPage',
label: conv({ hans: '标记图片时加入到监视列表', hant: '標記圖片時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.deliWatchUser (string)
// The watchlist setting of the user talk page if a notification is placed.
{
name: 'deliWatchUser',
label: conv({ hans: '标记图片时加入创建者讨论页到监视列表', hant: '標記圖片時加入建立者討論頁到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: conv({ hans: '保护', hant: '保護' }),
module: 'protect',
preferences: [
{
name: 'watchRequestedPages',
label: conv({ hans: '请求保护页面时加入到监视列表', hant: '請求保護頁面時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchPPTaggedPages',
label: conv({ hans: '标记保护模板时加入到监视列表', hant: '標記保護模板時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchProtectedPages',
label: conv({ hans: '保护时加入到监视列表', hant: '保護時加入到監視清單' }),
helptip: conv({ hans: '如果在保护后也标记页面,则使用标记页面的参数设置。', hant: '如果在保護後也標記頁面,則使用標記頁面的偏好設定。' }),
adminOnly: true,
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: '回退', // twinklefluff module
module: 'fluff',
preferences: [
// TwinkleConfig.autoMenuAfterRollback (bool)
// Option to automatically open the warning menu if the user talk page is opened post-reversion
{
name: 'autoMenuAfterRollback',
label: conv({ hans: '在Twinkle回退后自动打开用户讨论页上的Twinkle警告菜单', hant: '在Twinkle回退後自動打開使用者討論頁上的Twinkle警告選單' }),
helptip: conv({ hans: '仅在选取下方对应框时才执行', hant: '僅在選取下方對應框時才執行' }),
type: 'boolean'
},
// TwinkleConfig.openTalkPage (array)
// What types of actions that should result in opening of talk page
{
name: 'openTalkPage',
label: conv({ hans: '在这些类型的回退后打开用户讨论页', hant: '在這些類別的回退後打開使用者討論頁' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }) }
},
// TwinkleConfig.openTalkPageOnAutoRevert (bool)
// Defines if talk page should be opened when calling revert from contribs or recent changes pages. If set to true, openTalkPage defines then if talk page will be opened.
{
name: 'openTalkPageOnAutoRevert',
label: conv({ hans: '在从用户贡献及最近更改中发起回退时打开用户讨论页', hant: '在從使用者貢獻及近期變更中發起回退時打開使用者討論頁' }),
helptip: conv({ hans: '当它打开时,依赖上一个设置。', hant: '當它打開時,依賴上一個設定。' }),
type: 'boolean'
},
// TwinkleConfig.rollbackInPlace (bool)
//
{
name: 'rollbackInPlace',
label: conv({ hans: '在从用户贡献及最近更改中发起回退时不刷新页面', hant: '在從使用者貢獻及近期變更中發起回退時不重新整理頁面' }),
helptip: conv({ hans: '当它打开时,Twinkle将不会在从用户贡献及最近更改中发起回退时刷新页面,允许您一次性回退多个编辑。', hant: '當它打開時,Twinkle將不會在從使用者貢獻及近期變更中發起回退時重新整理頁面,允許您一次性回退多個編輯。' }),
type: 'boolean'
},
// TwinkleConfig.markRevertedPagesAsMinor (array)
// What types of actions that should result in marking edit as minor
{
name: 'markRevertedPagesAsMinor',
label: conv({ hans: '将这些类型的回退标记为小修改', hant: '將這些類別的回退標記為小修改' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }), torev: conv({ hans: '“恢复此版本”', hant: '「恢復此版本」' }) }
},
// TwinkleConfig.watchRevertedPages (array)
// What types of actions that should result in forced addition to watchlist
{
name: 'watchRevertedPages',
label: conv({ hans: '把这些类型的回退加入到监视列表', hant: '把這些類別的回退加入到監視清單' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }), torev: conv({ hans: '“恢复此版本”', hant: '「恢復此版本」' }) }
},
// TwinkleConfig.watchRevertedExpiry
// If any of the above items are selected, whether to expire the watch
{
name: 'watchRevertedExpiry',
label: conv({ hans: '当回退页面时,加入到监视列表的期限', hant: '當回退頁面時,加入到監視清單的期限' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.offerReasonOnNormalRevert (boolean)
// If to offer a prompt for extra summary reason for normal reverts, default to true
{
name: 'offerReasonOnNormalRevert',
label: conv({ hans: '常规回退时询问理由', hant: '常規回退時詢問理由' }),
helptip: conv({ hans: '“常规”回退是中间的那个[回退]链接。', hant: '「常規」回退是中間的那個[回退]連結。' }),
type: 'boolean'
},
{
name: 'confirmOnFluff',
label: conv({ hans: '回退前要求确认(所有设备)', hant: '回退前要求確認(所有裝置)' }),
helptip: conv({ hans: '对于使用移动设备的用户,或者意志不坚定的。', hant: '對於使用行動裝置的使用者,或者意志不堅定的。' }),
type: 'boolean'
},
{
name: 'confirmOnMobileFluff',
label: conv({ hans: '回退前要求确认(仅移动设备)', hant: '回退前要求確認(僅行動裝置)' }),
helptip: conv({ hans: '避免在移动设备意外执行回退。', hant: '避免在行動裝置意外執行回退。' }),
type: 'boolean'
},
// TwinkleConfig.showRollbackLinks (array)
// Where Twinkle should show rollback links:
// diff, others, mine, contribs, history, recent
// Note from TTO: |contribs| seems to be equal to |others| + |mine|, i.e. redundant, so I left it out heres
{
name: 'showRollbackLinks',
label: conv({ hans: '在这些页面上显示回退链接', hant: '在這些頁面上顯示回退連結' }),
type: 'set',
setValues: { diff: conv({ hans: '差异', hant: '差異' }), history: conv({ hans: '历史记录', hant: '歷史記錄' }), others: conv({ hans: '其它用户的贡献', hant: '其它使用者的貢獻' }), mine: conv({ hans: '我的贡献', hant: '我的貢獻' }), recentchanges: conv({ hans: '最近更改', hant: '近期變更' }), recentchangeslinked: conv({ hans: '相关更改', hant: '相關變更' }) }
},
{
name: 'customRevertSummary',
label: '回退理由',
helptip: conv({ hans: '在查看差异时可选,仅善意回退、常规回退、恢复此版本', hant: '在檢視差異時可選,僅善意回退、常規回退、恢復此版本' }),
type: 'customList',
customListValueTitle: '理由',
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: conv({ hans: '共享IP标记', hant: '共享IP標記' }),
module: 'shared',
preferences: [
{
name: 'markSharedIPAsMinor',
label: conv({ hans: '将共享IP标记标记为小修改', hant: '將共享IP標記標記為小修改' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '快速删除', hant: '快速刪除' }),
module: 'speedy',
preferences: [
{
name: 'speedySelectionStyle',
label: conv({ hans: '什么时候执行标记或删除', hant: '什麼時候執行標記或刪除' }),
type: 'enum',
enumValues: { buttonClick: conv({ hans: '当我点“提交”时', hant: '當我點「提交」時' }), radioClick: conv({ hans: '当我点一个选项时', hant: '當我點一個選項時' }) }
},
// TwinkleConfig.watchSpeedyPages (array)
// Whether to add speedy tagged pages to watchlist
{
name: 'watchSpeedyPages',
label: conv({ hans: '将以下理由加入到监视列表', hant: '將以下理由加入到監視清單' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteria,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder
},
// TwinkleConfig.watchSpeedyExpiry
// If any of the above items are selected, whether to expire the watch
{
name: 'watchSpeedyExpiry',
label: conv({ hans: '当标记页面时,加入到监视列表的期限', hant: '當標記頁面時,加入到監視清單的期限' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.markSpeedyPagesAsPatrolled (boolean)
// If, when applying speedy template to page, to mark the page as patrolled (if the page was reached from NewPages)
{
name: 'markSpeedyPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
type: 'boolean'
},
// TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array)
// What types of actions should result that the author of the page being notified of nomination
{
name: 'notifyUserOnSpeedyDeletionNomination',
label: conv({ hans: '仅在使用以下理由时通知页面创建者', hant: '僅在使用以下理由時通知頁面建立者' }),
helptip: conv({ hans: '尽管您在对话框中选择通知,通知仍只会在使用这些理由时发出。', hant: '儘管您在對話方塊中選擇通知,通知仍只會在使用這些理由時發出。' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteriaNotification,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder
},
// TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings)
// On what types of speedy deletion notifications shall the user be welcomed
// with a "firstarticle" notice if his talk page has not yet been created.
{
name: 'welcomeUserOnSpeedyDeletionNotification',
label: conv({ hans: '在使用以下理由时欢迎页面创建者', hant: '在使用以下理由時歡迎頁面建立者' }),
helptip: conv({ hans: '欢迎模板仅在用户被通知时加入,使用的模板是{{firstarticle}}。', hant: '歡迎模板僅在使用者被通知時加入,使用的模板是{{firstarticle}}。' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteriaNotification,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder
},
// TwinkleConfig.promptForSpeedyDeletionSummary (array of strings)
{
name: 'promptForSpeedyDeletionSummary',
label: conv({ hans: '使用以下理由删除时允许编辑删除理由', hant: '使用以下理由刪除時允許編輯刪除理由' }),
adminOnly: true,
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
// TwinkleConfig.openUserTalkPageOnSpeedyDelete (array of strings)
// What types of actions that should result user talk page to be opened when speedily deleting (admin only)
{
name: 'openUserTalkPageOnSpeedyDelete',
label: conv({ hans: '使用以下理由时打开用户讨论页', hant: '使用以下理由時打開使用者討論頁' }),
adminOnly: true,
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
// TwinkleConfig.deleteTalkPageOnDelete (boolean)
// If talk page if exists should also be deleted (CSD G8) when spedying a page (admin only)
{
name: 'deleteTalkPageOnDelete',
label: conv({ hans: '默认勾选“删除讨论页”', hant: '預設勾選「刪除討論頁」' }),
adminOnly: true,
type: 'boolean'
},
{
name: 'deleteRedirectsOnDelete',
label: conv({ hans: '默认勾选“删除重定向”', hant: '預設勾選「刪除重新導向」' }),
adminOnly: true,
type: 'boolean'
},
// TwinkleConfig.deleteSysopDefaultToDelete (boolean)
// Make the CSD screen default to "delete" instead of "tag" (admin only)
{
name: 'deleteSysopDefaultToDelete',
label: conv({ hans: '默认为直接删除而不是标记', hant: '預設為直接刪除而不是標記' }),
helptip: conv({ hans: '如果已放置快速删除标记,则永远默认为删除模式。', hant: '如果已放置快速刪除標記,則永遠預設為刪除模式。' }),
adminOnly: true,
type: 'boolean'
},
// TwinkleConfig.speedyWindowWidth (integer)
// Defines the width of the Twinkle SD window in pixels
{
name: 'speedyWindowWidth',
label: conv({ hans: '快速删除对话框宽度(像素)', hant: '快速刪除對話方塊寬度(像素)' }),
type: 'integer'
},
// TwinkleConfig.speedyWindowWidth (integer)
// Defines the width of the Twinkle SD window in pixels
{
name: 'speedyWindowHeight',
label: conv({ hans: '快速删除对话框高度(像素)', hant: '快速刪除對話方塊高度(像素)' }),
helptip: conv({ hans: '如果您有一台很大的显示器,您可以将此调高。', hant: '如果您有一台很大的顯示器,您可以將此調高。' }),
type: 'integer'
},
{
name: 'logSpeedyNominations',
label: conv({ hans: '在用户空间中记录所有快速删除提名', hant: '在使用者空間中記錄所有快速刪除提名' }),
helptip: conv({ hans: '非管理员无法访问到已删除的贡献,用户空间日志提供了一个很好的方法来记录这些历史。', hant: '非管理員無法存取到已刪除的貢獻,使用者空間日誌提供了一個很好的方法來記錄這些歷史。' }),
type: 'boolean'
},
{
name: 'speedyLogPageName',
label: conv({ hans: '在此页保留日志', hant: '在此頁保留日誌' }),
helptip: conv({ hans: '在此框中输入子页面名称,您将在User:<i>用户名</i>/<i>子页面</i>找到CSD日志。仅在启用日志时工作。', hant: '在此框中輸入子頁面名稱,您將在User:<i>使用者名稱</i>/<i>子頁面</i>找到CSD日誌。僅在啟用日誌時工作。' }),
type: 'string'
},
{
name: 'noLogOnSpeedyNomination',
label: conv({ hans: '在使用以下理由时不做记录', hant: '在使用以下理由時不做記錄' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
{
name: 'enlargeG11Input',
label: conv({ hans: '扩大CSD G11的按钮', hant: '擴大CSD G11的按鈕' }),
helptip: conv({ hans: '扩为默认的两倍大。', hant: '擴為預設的兩倍大。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '标记', hant: '標記' }),
module: 'tag',
preferences: [
{
name: 'watchTaggedPages',
label: conv({ hans: '标记时加入到监视列表', hant: '標記時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchMergeDiscussions',
label: conv({ hans: '加入合并讨论时监视讨论页', hant: '加入合併討論時監視討論頁' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'markTaggedPagesAsMinor',
label: conv({ hans: '将标记标记为小修改', hant: '將標記標記為小修改' }),
type: 'boolean'
},
{
name: 'markTaggedPagesAsPatrolled',
label: conv({ hans: '默认勾选“标记页面为已巡查”框', hant: '預設勾選「標記頁面為已巡查」框' }),
type: 'boolean'
},
{
name: 'groupByDefault',
label: conv({ hans: '默认勾选“合并到{{multiple issues}}”复选框', hant: '預設勾選「合併到{{multiple issues}}」核取方塊' }),
type: 'boolean'
},
{
name: 'tagArticleSortOrder',
label: conv({ hans: '条目标记的默认查看方式', hant: '條目標記的預設檢視方式' }),
type: 'enum',
enumValues: { cat: conv({ hans: '按类型', hant: '按類別' }), alpha: '按字母' }
},
{
name: 'customTagList',
label: conv({ hans: '自定义条目维护标记', hant: '自訂條目維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customFileTagList',
label: conv({ hans: '自定义文件维护标记', hant: '自訂檔案維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customRedirectTagList',
label: conv({ hans: '自定义重定向维护标记', hant: '自訂重新導向維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: '小作品',
module: 'stub',
preferences: [
{
name: 'watchStubbedPages',
label: conv({ hans: '标记时加入到监视列表', hant: '標記時加入到監視清單' }),
type: 'boolean'
},
{
name: 'markStubbedPagesAsMinor',
label: conv({ hans: '将小作品标记为小修改', hant: '將小作品標記為小修改' }),
type: 'boolean'
},
{
name: 'markStubbedPagesAsPatrolled',
label: conv({ hans: '默认勾选“标记页面为已巡查”框', hant: '預設勾選「標記頁面為已巡查」框' }),
type: 'boolean'
},
{
name: 'stubArticleSortOrder',
label: conv({ hans: '条目小作品的默认查看方式', hant: '條目小作品的預設檢視方式' }),
type: 'enum',
enumValues: { cat: conv({ hans: '按类型', hant: '按類別' }), alpha: '按字母' }
},
{
name: 'customStubList',
label: conv({ hans: '自定义条目小作品标记', hant: '自訂條目小作品標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: '通告',
module: 'talkback',
preferences: [
{
name: 'markTalkbackAsMinor',
label: conv({ hans: '将通告标记为小修改', hant: '將通告標記為小修改' }),
type: 'boolean'
},
{
name: 'insertTalkbackSignature',
label: conv({ hans: '通告时加入签名', hant: '通告時加入簽名' }),
helptip: conv({ hans: 'Flow页除外。', hant: 'Flow頁除外。' }),
type: 'boolean'
},
{
name: 'talkbackHeading',
label: conv({ hans: '通告所用的小节标题', hant: '通告所用的小節標題' }),
type: 'string'
},
{
name: 'mailHeading',
label: conv({ hans: '“有新邮件”所用的小节标题', hant: '「有新郵件」所用的小節標題' }),
type: 'string'
}
]
},
{
title: conv({ hans: '取消链入', hant: '取消連入' }),
module: 'unlink',
preferences: [
// TwinkleConfig.unlinkNamespaces (array)
// In what namespaces unlink should happen, default in 0 (article) and 100 (portal)
{
name: 'unlinkNamespaces',
label: conv({ hans: '取消以下命名空间中的反向链接', hant: '取消以下命名空間中的反向連結' }),
helptip: conv({ hans: '请避免选择讨论页,因这样会导致Twinkle试图修改讨论存档。', hant: '請避免選擇討論頁,因這樣會導致Twinkle試圖修改討論存檔。' }),
type: 'set',
setValues: Twinkle.config.commonSets.namespacesNoSpecial
}
]
},
{
title: conv({ hans: '警告用户', hant: '警告使用者' }),
module: 'warn',
preferences: [
// TwinkleConfig.defaultWarningGroup (int)
// if true, watch the page which has been dispatched an warning or notice, if false, default applies
{
name: 'defaultWarningGroup',
label: conv({ hans: '默认警告级别', hant: '預設警告級別' }),
type: 'enum',
enumValues: {
1: '1:提醒',
2: '2:注意',
3: '3:警告',
4: conv({ hans: '4:最后警告', hant: '4:最後警告' }),
5: '4im:唯一警告',
6: conv({ hans: '单层级提醒', hant: '單層級提醒' }),
7: conv({ hans: '单层级警告', hant: '單層級警告' }),
// 8 was used for block templates before #260
9: conv({ hans: '自定义警告', hant: '自訂警告' }),
10: '所有警告模板',
11: conv({ hans: '自动选择层级(1-4)', hant: '自動選擇層級(1-4)' })
}
},
// TwinkleConfig.combinedSingletMenus (boolean)
// if true, show one menu with both single-issue notices and warnings instead of two separately
{
name: 'combinedSingletMenus',
label: conv({ hans: '将两个单层级菜单合并成一个', hant: '將兩個單層級選單合併成一個' }),
helptip: conv({ hans: '当启用此选项时,无论默认警告级别选择单层级通知或单层级警告皆属于此项。', hant: '當啟用此選項時,無論預設警告級別選擇單層級通知或單層級警告皆屬於此項。' }),
type: 'boolean'
},
// TwinkleConfig.showSharedIPNotice may take arguments:
// true: to show shared ip notice if an IP address
// false: to not print the notice
{
name: 'showSharedIPNotice',
label: conv({ hans: '在IP讨论页上显示附加信息', hant: '在IP討論頁上顯示附加資訊' }),
helptip: '使用的模板是{{SharedIPAdvice}}。',
type: 'boolean'
},
// TwinkleConfig.watchWarnings (string)
// Watchlist setting for the page which has been dispatched an warning or notice
{
name: 'watchWarnings',
label: conv({ hans: '警告时加入用户讨论页到监视列表', hant: '警告時加入使用者討論頁到監視清單' }),
helptip: conv({ hans: '注意:如果对方使用Flow,对应讨论串总会加到监视列表中。', hant: '注意:如果對方使用Flow,對應討論串總會加到監視清單中。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.oldSelect (boolean)
// if true, use the native select menu rather the jquery chosen-based one
{
name: 'oldSelect',
label: conv({ hans: '使用不可搜索的经典菜单', hant: '使用不可搜尋的經典選單' }),
type: 'boolean'
},
{
name: 'customWarningList',
label: conv({ hans: '自定义警告模板', hant: '自訂警告模板' }),
helptip: conv({ hans: '您可以加入模板或用户子页面。自定义警告会出现在警告对话框中“自定义警告”一节。', hant: '您可以加入模板或使用者子頁面。自訂警告會出現在警告對話方塊中「自訂警告」一節。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字(和编辑摘要)', hant: '顯示的文字(和編輯摘要)' })
}
]
},
{
title: conv({ hans: '欢迎用户', hant: '歡迎使用者' }),
module: 'welcome',
preferences: [
{
name: 'topWelcomes',
label: conv({ hans: '将欢迎放在用户讨论页的最上方', hant: '將歡迎放在使用者討論頁的最上方' }),
type: 'boolean'
},
{
name: 'watchWelcomes',
label: conv({ hans: '在欢迎时将用户讨论页加入监视列表', hant: '在歡迎時將使用者討論頁加入監視清單' }),
helptip: conv({ hans: '您将可以关注新手如何与他人协作,并能够适时地提供帮助。', hant: '您將可以關注新手如何與他人協作,並能夠適時地提供幫助。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
/*
{
name: 'insertUsername',
label: wgULS('Add your username to the template (where applicable)'),
helptip: "Some welcome templates have an opening sentence like \"Hi, I'm <username>. Welcome\" etc. If you turn off this option, these templates will not display your username in that way.",
type: 'boolean'
},
*/
{
name: 'quickWelcomeMode',
label: conv({ hans: '在差异页面单击“欢迎”链接时将会', hant: '在差異頁面點擊「歡迎」連結時將會' }),
helptip: conv({ hans: '如果您选择自动欢迎,将会使用下方指定的模板。', hant: '如果您選擇自動歡迎,將會使用下方指定的模板。' }),
type: 'enum',
enumValues: { auto: conv({ hans: '自动欢迎', hant: '自動歡迎' }), norm: conv({ hans: '要求您选择模板', hant: '要求您選擇模板' }) }
},
{
name: 'quickWelcomeTemplate',
label: conv({ hans: '自动欢迎时所使用的模板', hant: '自動歡迎時所使用的模板' }),
helptip: conv({ hans: '输入欢迎模板的名称,不包含大括号,将会加入给定的条目链接。', hant: '輸入歡迎模板的名稱,不包含大括號,將會加入給定的條目連結。' }),
type: 'string'
},
{
name: 'customWelcomeList',
label: conv({ hans: '自定义欢迎模板', hant: '自訂歡迎模板' }),
helptip: conv({ hans: '您可以加入其他欢迎模板,或是欢迎模板的用户子页面(以User:开头)。别忘了这些模板会在用户讨论页上替换引用。', hant: '您可以加入其他歡迎模板,或是歡迎模板的使用者子頁面(以User:開頭)。別忘了這些模板會在使用者討論頁上替換引用。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customWelcomeSignature',
label: conv({ hans: '在自定义模板中自动签名', hant: '在自訂模板中自動簽名' }),
helptip: conv({ hans: '如果您的自动欢迎模板包含内置签名,请关闭此项。', hant: '如果您的自動歡迎模板包含內建簽名,請關閉此項。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '存废讨论', hant: '存廢討論' }),
module: 'xfd',
preferences: [
{
name: 'logXfdNominations',
label: conv({ hans: '在用户空间中记录所有存废讨论提名', hant: '在使用者空間中記錄所有存廢討論提名' }),
helptip: conv({ hans: '该日志供您追踪所有通过Twinkle提交的存废讨论', hant: '該日誌供您追蹤所有透過Twinkle提交的存廢討論' }),
type: 'boolean'
},
{
name: 'xfdLogPageName',
label: conv({ hans: '在此页保留日志', hant: '在此頁保留日誌' }),
helptip: conv({ hans: '在此框中输入子页面名称,您将在User:<i>用户名</i>/<i>子页面</i>找到XFD日志。仅在启用日志时工作。', hant: '在此框中輸入子頁面名稱,您將在User:<i>使用者名稱</i>/<i>子頁面</i>找到XFD日誌。僅在啟用日誌時工作。' }),
type: 'string'
},
{
name: 'noLogOnXfdNomination',
label: conv({ hans: '在使用以下理由时不做记录', hant: '在使用以下理由時不做記錄' }),
type: 'set',
setValues: Twinkle.config.commonSets.xfdCriteria,
setDisplayOrder: Twinkle.config.commonSets.xfdCriteriaDisplayOrder
},
// TwinkleConfig.xfdWatchPage (string)
// The watchlist setting of the page being nominated for XfD.
{
name: 'xfdWatchPage',
label: conv({ hans: '加入提名的页面到监视列表', hant: '加入提名的頁面到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.xfdWatchDiscussion (string)
// The watchlist setting of the newly created XfD page (for those processes that create discussion pages for each nomination),
// or the list page for the other processes.
{
name: 'xfdWatchDiscussion',
label: conv({ hans: '加入存废讨论页到监视列表', hant: '加入存廢討論頁到監視清單' }),
helptip: conv({ hans: '当日的页面。', hant: '當日的頁面。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.xfdWatchUser (string)
// The watchlist setting of the user talk page if they receive a notification.
{
name: 'xfdWatchUser',
label: conv({ hans: '加入创建者讨论页到监视列表(在通知时)', hant: '加入建立者討論頁到監視清單(在通知時)' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'markXfdPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
helptip: conv({ hans: '基于技术原因,页面仅会在由Special:NewPages到达时被标记为已巡查。', hant: '基於技術原因,頁面僅會在由Special:NewPages到達時被標記為已巡查。' }),
type: 'boolean'
},
{
name: 'FwdCsdToXfd',
label: conv({ hans: '提删类型增加转交自快速删除候选', hant: '提刪類別增加轉交自快速刪除候選' }),
helptip: conv({ hans: '请确保您充分了解[[Wikipedia:快速删除方针]]才开启此功能。', hant: '請確保您充分了解[[Wikipedia:快速刪除方針]]才開啟此功能。' }),
type: 'boolean'
},
{
name: 'afdDefaultCategory',
label: conv({ hans: '默认提删类型', hant: '預設提刪類別' }),
helptip: conv({ hans: '若选择“相同于上次选择”将使用localStorage来记忆。', hant: '若選擇「相同於上次選擇」將使用localStorage來記憶。' }),
type: 'enum',
enumValues: { delete: conv({ hans: '删除', hant: '刪除' }), same: conv({ hans: '相同于上次选择', hant: '相同於上次選擇' }) }
},
{
name: 'afdFameDefaultReason',
label: conv({ hans: '默认关注度提删理由', hant: '預設關注度提刪理由' }),
helptip: conv({ hans: '用于批量提删。', hant: '用於批次提刪。' }),
type: 'string'
},
{
name: 'afdSubstubDefaultReason',
label: conv({ hans: '默认小小作品提删理由', hant: '預設小小作品提刪理由' }),
helptip: conv({ hans: '用于批量提删。', hant: '用於批次提刪。' }),
type: 'string'
}
]
},
{
title: conv({ hans: '关闭存废讨论', hant: '關閉存廢討論' }),
module: 'close',
preferences: [
{
name: 'XfdClose',
label: conv({ hans: '在存废讨论显示关闭讨论按钮', hant: '在存廢討論顯示關閉討論按鈕' }),
helptip: conv({ hans: '请确保您充分了解[[Wikipedia:关闭存废讨论指引]]才开启此功能。', hant: '請確保您充分了解[[Wikipedia:關閉存廢討論指引]]才開啟此功能。' }),
type: 'enum',
enumValues: { hide: conv({ hans: '不显示', hant: '不顯示' }), nonadminonly: conv({ hans: '只包含非管理员可使用选项', hant: '只包含非管理員可使用選項' }), all: conv({ hans: '显示所有选项', hant: '顯示所有選項' }) }
}
]
},
{
title: conv({ hans: '侵犯著作权', hant: '侵犯著作權' }),
module: 'copyvio',
preferences: [
// TwinkleConfig.copyvioWatchPage (string)
// The watchlist setting of the page being nominated for XfD.
{
name: 'copyvioWatchPage',
label: conv({ hans: '加入提报的页面到监视列表', hant: '加入提報的頁面到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.copyvioWatchUser (string)
// The watchlist setting of the user if he receives a notification.
{
name: 'copyvioWatchUser',
label: conv({ hans: '加入创建者讨论页到监视列表(在通知时)', hant: '加入建立者討論頁到監視清單(在通知時)' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.markCopyvioPagesAsPatrolled (boolean)
// If, when applying copyvio template to page, to mark the page as patrolled (if the page was reached from NewPages)
{
name: 'markCopyvioPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
helptip: conv({ hans: '基于技术原因,页面仅会在由Special:NewPages到达时被标记为已巡查。', hant: '基於技術原因,頁面僅會在由Special:NewPages到達時被標記為已巡查。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '隐藏', hant: '隱藏' }),
hidden: true,
preferences: [
// twinkle.js: portlet setup
{
name: 'portletArea',
type: 'string'
},
{
name: 'portletId',
type: 'string'
},
{
name: 'portletName',
type: 'string'
},
{
name: 'portletType',
type: 'string'
},
{
name: 'portletNext',
type: 'string'
},
// twinklefluff.js: defines how many revision to query maximum, maximum possible is 50, default is 50
{
name: 'revertMaxRevisions',
type: 'integer'
},
// twinklebatchdelete.js: How many pages should be processed maximum
{
name: 'batchMax',
type: 'integer',
adminOnly: true
},
// How many pages should be processed at a time by deprod and batchdelete/protect/undelete
{
name: 'batchChunks',
type: 'integer',
adminOnly: true
}
]
}
]; // end of Twinkle.config.sections
Twinkle.config.init = function twinkleconfigInit() {
// create the config page at Twinkle.getPref('configPage')
if (mw.config.get('wgPageName') === Twinkle.getPref('configPage') &&
mw.config.get('wgAction') === 'view') {
if (!document.getElementById('twinkle-config')) {
return; // maybe the page is misconfigured, or something - but any attempt to modify it will be pointless
}
// set style (the url() CSS function doesn't seem to work from wikicode - ?!)
document.getElementById('twinkle-config-titlebar').style.backgroundImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB%2FqqA%2BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhQTFRFr73ZobTPusjdsMHZp7nVwtDhzNbnwM3fu8jdq7vUt8nbxtDkw9DhpbfSvMrfssPZqLvVztbno7bRrr7W1d%2Fs1N7qydXk0NjpkW7Q%2BgAAADVJREFUeNoMwgESQCAAAMGLkEIi%2FP%2BnbnbpdB59app5Vdg0sXAoMZCpGoFbK6ciuy6FX4ABAEyoAef0BXOXAAAAAElFTkSuQmCC)';
var contentdiv = document.getElementById('twinkle-config-content');
contentdiv.textContent = ''; // clear children
// let user know about possible conflict with monobook.js/vector.js file
// (settings in that file will still work, but they will be overwritten by twinkleoptions.js settings)
var contentnotice = document.createElement('p');
// I hate innerHTML, but this is one thing it *is* good for...
contentnotice.innerHTML = '<b>' + conv({ hans: '在这里修改您的参数设置之前,', hant: '在這裡修改您的偏好設定之前,' }) + '</b>' + conv({ hans: '确认您已移除了', hant: '確認您已移除了' }) + '<a href="' + mw.util.getUrl('Special:MyPage/skin.js') + '" title="Special:MyPage/skin.js">' + conv({ hans: '用户JavaScript文件', hant: '使用者JavaScript檔案' }) + '</a>' + conv({ hans: '中任何旧的', hant: '中任何舊的' }) + '<code>FriendlyConfig</code>' + conv({ hans: '设置。', hant: '設定。' });
contentdiv.appendChild(contentnotice);
// look and see if the user does in fact have any old settings in their skin JS file
var skinjs = new Morebits.wiki.page('User:' + mw.config.get('wgUserName') + '/' + mw.config.get('skin') + '.js');
skinjs.setCallbackParameters(contentnotice);
skinjs.load(Twinkle.config.legacyPrefsNotice);
// start a table of contents
var toctable = document.createElement('div');
toctable.className = 'toc';
toctable.style.marginLeft = '0.4em';
// create TOC title
var toctitle = document.createElement('div');
toctitle.id = 'toctitle';
var toch2 = document.createElement('h2');
toch2.textContent = conv({ hans: '目录 ', hant: '目錄 ' });
toctitle.appendChild(toch2);
// add TOC show/hide link
var toctoggle = document.createElement('span');
toctoggle.className = 'toctoggle';
toctoggle.appendChild(document.createTextNode('['));
var toctogglelink = document.createElement('a');
toctogglelink.className = 'internal';
toctogglelink.setAttribute('href', '#tw-tocshowhide');
toctogglelink.textContent = conv({ hans: '隐藏', hant: '隱藏' });
toctoggle.appendChild(toctogglelink);
toctoggle.appendChild(document.createTextNode(']'));
toctitle.appendChild(toctoggle);
toctable.appendChild(toctitle);
// create item container: this is what we add stuff to
var tocul = document.createElement('ul');
toctogglelink.addEventListener('click', function twinkleconfigTocToggle() {
var $tocul = $(tocul);
$tocul.toggle();
if ($tocul.find(':visible').length) {
toctogglelink.textContent = conv({ hans: '隐藏', hant: '隱藏' });
} else {
toctogglelink.textContent = conv({ hans: '显示', hant: '顯示' });
}
}, false);
toctable.appendChild(tocul);
contentdiv.appendChild(toctable);
var contentform = document.createElement('form');
contentform.setAttribute('action', 'javascript:void(0)'); // was #tw-save - changed to void(0) to work around Chrome issue
contentform.addEventListener('submit', Twinkle.config.save, true);
contentdiv.appendChild(contentform);
var container = document.createElement('table');
container.style.width = '100%';
contentform.appendChild(container);
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // i.e. "continue" in this context
}
// add to TOC
var tocli = document.createElement('li');
tocli.className = 'toclevel-1';
var toca = document.createElement('a');
toca.setAttribute('href', '#' + section.module);
toca.appendChild(document.createTextNode(section.title));
tocli.appendChild(toca);
tocul.appendChild(tocli);
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.setAttribute('colspan', '3');
var heading = document.createElement('h4');
heading.style.borderBottom = '1px solid gray';
heading.style.marginTop = '0.2em';
heading.id = section.module;
heading.appendChild(document.createTextNode(section.title));
cell.appendChild(heading);
row.appendChild(cell);
container.appendChild(row);
var rowcount = 1; // for row banding
// add each of the preferences to the form
$(section.preferences).each(function(prefkey, pref) {
if (pref.adminOnly && !Morebits.userIsSysop) {
return true; // i.e. "continue" in this context
}
row = document.createElement('tr');
row.style.marginBottom = '0.2em';
// create odd row banding
if (rowcount++ % 2 === 0) {
row.style.backgroundColor = 'rgba(128, 128, 128, 0.1)';
}
cell = document.createElement('td');
var label, input, gotPref = Twinkle.getPref(pref.name);
switch (pref.type) {
case 'boolean': // create a checkbox
cell.setAttribute('colspan', '2');
label = document.createElement('label');
input = document.createElement('input');
input.setAttribute('type', 'checkbox');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
if (gotPref === true) {
input.setAttribute('checked', 'checked');
}
label.appendChild(input);
label.appendChild(document.createTextNode(pref.label));
cell.appendChild(label);
break;
case 'string': // create an input box
case 'integer':
// add label to first column
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add input box to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
if (pref.type === 'integer') {
input.setAttribute('size', 6);
input.setAttribute('type', 'number');
input.setAttribute('step', '1'); // integers only
}
if (gotPref) {
input.setAttribute('value', gotPref);
}
cell.appendChild(input);
break;
case 'enum': // create a combo box
// add label to first column
// note: duplicates the code above, under string/integer
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add input box to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
input = document.createElement('select');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
var optionExists = false;
$.each(pref.enumValues, function(enumvalue, enumdisplay) {
var option = document.createElement('option');
option.setAttribute('value', enumvalue);
if ((gotPref === enumvalue) ||
// Hack to convert old boolean watchlist prefs
// to corresponding enums (added in v2.1)
(typeof gotPref === 'boolean' &&
((gotPref && enumvalue === 'yes') ||
(!gotPref && enumvalue === 'no')))) {
option.setAttribute('selected', 'selected');
optionExists = true;
}
option.appendChild(document.createTextNode(enumdisplay));
input.appendChild(option);
});
// Append user-defined value to options
if (!optionExists) {
var option = document.createElement('option');
option.setAttribute('value', gotPref);
option.setAttribute('selected', 'selected');
option.appendChild(document.createTextNode(gotPref));
input.appendChild(option);
}
cell.appendChild(input);
break;
case 'set': // create a set of check boxes
// add label first of all
cell.setAttribute('colspan', '2');
label = document.createElement('label'); // not really necessary to use a label element here, but we do it for consistency of styling
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
var checkdiv = document.createElement('div');
checkdiv.style.paddingLeft = '1em';
var worker = function(itemkey, itemvalue) {
var checklabel = document.createElement('label');
checklabel.style.marginRight = '0.7em';
checklabel.style.display = 'inline-block';
var check = document.createElement('input');
check.setAttribute('type', 'checkbox');
check.setAttribute('id', pref.name + '_' + itemkey);
check.setAttribute('name', pref.name + '_' + itemkey);
if (gotPref && gotPref.indexOf(itemkey) !== -1) {
check.setAttribute('checked', 'checked');
}
// cater for legacy integer array values for unlinkNamespaces (this can be removed a few years down the track...)
if (pref.name === 'unlinkNamespaces') {
if (gotPref && gotPref.indexOf(parseInt(itemkey, 10)) !== -1) {
check.setAttribute('checked', 'checked');
}
}
checklabel.appendChild(check);
checklabel.appendChild(document.createTextNode(itemvalue));
checkdiv.appendChild(checklabel);
};
if (pref.setDisplayOrder) {
// add check boxes according to the given display order
$.each(pref.setDisplayOrder, function(itemkey, item) {
worker(item, pref.setValues[item]);
});
} else {
// add check boxes according to the order it gets fed to us (probably strict alphabetical)
$.each(pref.setValues, worker);
}
cell.appendChild(checkdiv);
break;
case 'customList':
// add label to first column
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add button to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
var button = document.createElement('button');
button.setAttribute('id', pref.name);
button.setAttribute('name', pref.name);
button.setAttribute('type', 'button');
button.addEventListener('click', Twinkle.config.listDialog.display, false);
// use jQuery data on the button to store the current config value
$(button).data({
value: gotPref,
pref: pref
});
button.appendChild(document.createTextNode(conv({ hans: '编辑项目', hant: '編輯項目' })));
cell.appendChild(button);
break;
default:
alert('twinkleconfig: 未知类型的属性 ' + pref.name);
break;
}
row.appendChild(cell);
// add help tip
cell = document.createElement('td');
cell.style.fontSize = '90%';
cell.style.color = 'gray';
if (pref.helptip) {
// convert mentions of templates in the helptip to clickable links
cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g,
'{{<a href="' + mw.util.getUrl('Template:') + '$1" target="_blank">$1</a>}}')
.replace(/\[\[(.+?)]]/g,
'<a href="' + mw.util.getUrl('') + '$1" target="_blank">$1</a>');
}
// add reset link (custom lists don't need this, as their config value isn't displayed on the form)
if (pref.type !== 'customList') {
var resetlink = document.createElement('a');
resetlink.setAttribute('href', '#tw-reset');
resetlink.setAttribute('id', 'twinkle-config-reset-' + pref.name);
resetlink.addEventListener('click', Twinkle.config.resetPrefLink, false);
resetlink.style.cssFloat = 'right';
resetlink.style.margin = '0 0.6em';
resetlink.appendChild(document.createTextNode(conv({ hans: '复位', hant: '復位' })));
cell.appendChild(resetlink);
}
row.appendChild(cell);
container.appendChild(row);
return true;
});
return true;
});
var footerbox = document.createElement('div');
footerbox.setAttribute('id', 'twinkle-config-buttonpane');
footerbox.style.backgroundColor = '#BCCADF';
footerbox.style.padding = '0.5em';
var button = document.createElement('button');
button.setAttribute('id', 'twinkle-config-submit');
button.setAttribute('type', 'submit');
button.appendChild(document.createTextNode(conv({ hans: '保存修改', hant: '儲存修改' })));
footerbox.appendChild(button);
var footerspan = document.createElement('span');
footerspan.className = 'plainlinks';
footerspan.style.marginLeft = '2.4em';
footerspan.style.fontSize = '90%';
var footera = document.createElement('a');
footera.setAttribute('href', '#tw-reset-all');
footera.setAttribute('id', 'twinkle-config-resetall');
footera.addEventListener('click', Twinkle.config.resetAllPrefs, false);
footera.appendChild(document.createTextNode(conv({ hans: '恢复默认', hant: '恢復預設' })));
footerspan.appendChild(footera);
footerbox.appendChild(footerspan);
contentform.appendChild(footerbox);
// since all the section headers exist now, we can try going to the requested anchor
if (window.location.hash) {
var loc = window.location.hash;
window.location.hash = '';
window.location.hash = loc;
}
} else if (mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user &&
mw.config.get('wgTitle').indexOf(mw.config.get('wgUserName')) === 0 &&
mw.config.get('wgPageName').slice(-3) === '.js') {
var box = document.createElement('div');
// Styled in twinkle.css
box.setAttribute('id', 'twinkle-config-headerbox');
var link,
scriptPageName = mw.config.get('wgPageName').slice(mw.config.get('wgPageName').lastIndexOf('/') + 1,
mw.config.get('wgPageName').lastIndexOf('.js'));
if (scriptPageName === 'twinkleoptions') {
// place "why not try the preference panel" notice
box.setAttribute('class', 'config-twopt-box');
if (mw.config.get('wgArticleId') > 0) { // page exists
box.appendChild(document.createTextNode(conv({ hans: '这页包含您的Twinkle参数设置,您可使用', hant: '這頁包含您的Twinkle偏好設定,您可使用' })));
} else { // page does not exist
box.appendChild(document.createTextNode(conv({ hans: '您可配置您的Twinkle,通过使用', hant: '您可配置您的Twinkle,通過使用' })));
}
link = document.createElement('a');
link.setAttribute('href', mw.util.getUrl(Twinkle.getPref('configPage')));
link.appendChild(document.createTextNode(conv({ hans: 'Twinkle参数设置面板', hant: 'Twinkle偏好設定面板' })));
box.appendChild(link);
box.appendChild(document.createTextNode(conv({ hans: ',或直接编辑本页。', hant: ',或直接編輯本頁。' })));
$(box).insertAfter($('#contentSub'));
} else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].indexOf(scriptPageName) !== -1) {
// place "Looking for Twinkle options?" notice
box.setAttribute('class', 'config-userskin-box');
box.appendChild(document.createTextNode(conv({ hans: '如果您想配置您的Twinkle,请使用', hant: '如果您想配置您的Twinkle,請使用' })));
link = document.createElement('a');
link.setAttribute('href', mw.util.getUrl(Twinkle.getPref('configPage')));
link.appendChild(document.createTextNode(conv({ hans: 'Twinkle参数设置面板', hant: 'Twinkle偏好設定面板' })));
box.appendChild(link);
box.appendChild(document.createTextNode('。'));
$(box).insertAfter($('#contentSub'));
}
}
};
// Morebits.wiki.page callback from init code
Twinkle.config.legacyPrefsNotice = function twinkleconfigLegacyPrefsNotice(pageobj) {
var text = pageobj.getPageText();
var contentnotice = pageobj.getCallbackParameters();
if (text.indexOf('TwinkleConfig') !== -1 || text.indexOf('FriendlyConfig') !== -1) {
contentnotice.innerHTML = '<table class="plainlinks ombox ombox-content"><tr><td class="mbox-image">' +
'<img alt="" src="http://upload.wikimedia.org/wikipedia/en/3/38/Imbox_content.png" /></td>' +
'<td class="mbox-text"><p><big><b>在这里修改您的参数设置之前,</b>您必须移除在用户JavaScript文件中任何旧的Friendly设置。</big></p>' +
'<p>要这样做,您可以<a href="' + mw.config.get('wgScript') + '?title=User:' + encodeURIComponent(mw.config.get('wgUserName')) + '/' + mw.config.get('skin') + '.js&action=edit" target="_blank"><b>编辑您的个人JavaScript</b></a>。删除提到<code>FriendlyConfig</code>的代码。</p>' +
'</td></tr></table>';
} else {
$(contentnotice).remove();
}
};
// custom list-related stuff
Twinkle.config.listDialog = {};
Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow(dlgtable, value, label) {
var contenttr = document.createElement('tr');
// "remove" button
var contenttd = document.createElement('td');
var removeButton = document.createElement('button');
removeButton.setAttribute('type', 'button');
removeButton.addEventListener('click', function() {
$(contenttr).remove();
}, false);
removeButton.textContent = '移除';
contenttd.appendChild(removeButton);
contenttr.appendChild(contenttd);
// value input box
contenttd = document.createElement('td');
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.className = 'twinkle-config-customlist-value';
input.style.width = '97%';
if (value) {
input.setAttribute('value', value);
}
contenttd.appendChild(input);
contenttr.appendChild(contenttd);
// label input box
contenttd = document.createElement('td');
input = document.createElement('input');
input.setAttribute('type', 'text');
input.className = 'twinkle-config-customlist-label';
input.style.width = '98%';
if (label) {
input.setAttribute('value', label);
}
contenttd.appendChild(input);
contenttr.appendChild(contenttd);
dlgtable.appendChild(contenttr);
};
Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) {
var $prefbutton = $(e.target);
var curvalue = $prefbutton.data('value');
var curpref = $prefbutton.data('pref');
var dialog = new Morebits.simpleWindow(720, 400);
dialog.setTitle(curpref.label);
dialog.setScriptName(conv({ hans: 'Twinkle参数设置', hant: 'Twinkle偏好設定' }));
var dialogcontent = document.createElement('div');
var dlgtable = document.createElement('table');
dlgtable.className = 'wikitable';
dlgtable.style.margin = '1.4em 1em';
dlgtable.style.width = '97%';
var dlgtbody = document.createElement('tbody');
// header row
var dlgtr = document.createElement('tr');
// top-left cell
var dlgth = document.createElement('th');
dlgth.style.width = '5%';
dlgtr.appendChild(dlgth);
// value column header
dlgth = document.createElement('th');
dlgth.style.width = '35%';
dlgth.textContent = curpref.customListValueTitle ? curpref.customListValueTitle : conv({ hans: '数值', hant: '數值' });
dlgtr.appendChild(dlgth);
// label column header
dlgth = document.createElement('th');
dlgth.style.width = '60%';
dlgth.textContent = curpref.customListLabelTitle ? curpref.customListLabelTitle : conv({ hans: '标签', hant: '標籤' });
dlgtr.appendChild(dlgth);
dlgtbody.appendChild(dlgtr);
// content rows
var gotRow = false;
$.each(curvalue, function(k, v) {
gotRow = true;
Twinkle.config.listDialog.addRow(dlgtbody, v.value, v.label);
});
// if there are no values present, add a blank row to start the user off
if (!gotRow) {
Twinkle.config.listDialog.addRow(dlgtbody);
}
// final "add" button
var dlgtfoot = document.createElement('tfoot');
dlgtr = document.createElement('tr');
var dlgtd = document.createElement('td');
dlgtd.setAttribute('colspan', '3');
var addButton = document.createElement('button');
addButton.style.minWidth = '8em';
addButton.setAttribute('type', 'button');
addButton.addEventListener('click', function() {
Twinkle.config.listDialog.addRow(dlgtbody);
}, false);
addButton.textContent = '添加';
dlgtd.appendChild(addButton);
dlgtr.appendChild(dlgtd);
dlgtfoot.appendChild(dlgtr);
dlgtable.appendChild(dlgtbody);
dlgtable.appendChild(dlgtfoot);
dialogcontent.appendChild(dlgtable);
// buttonpane buttons: [Save changes] [Reset] [Cancel]
var button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
Twinkle.config.listDialog.save($prefbutton, dlgtbody);
dialog.close();
}, false);
button.textContent = conv({ hans: '保存修改', hant: '儲存修改' });
dialogcontent.appendChild(button);
button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
Twinkle.config.listDialog.reset($prefbutton, dlgtbody);
}, false);
button.textContent = conv({ hans: '复位', hant: '復位' });
dialogcontent.appendChild(button);
button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
dialog.close(); // the event parameter on this function seems to be broken
}, false);
button.textContent = '取消';
dialogcontent.appendChild(button);
dialog.setContent(dialogcontent);
dialog.display();
};
// Resets the data value, re-populates based on the new (default) value, then saves the
// old data value again (less surprising behaviour)
Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset(button, tbody) {
// reset value on button
var $button = $(button);
var curpref = $button.data('pref');
var oldvalue = $button.data('value');
Twinkle.config.resetPref(curpref);
// reset form
var $tbody = $(tbody);
$tbody.find('tr').slice(1).remove(); // all rows except the first (header) row
// add the new values
var curvalue = $button.data('value');
$.each(curvalue, function(k, v) {
Twinkle.config.listDialog.addRow(tbody, v.value, v.label);
});
// save the old value
$button.data('value', oldvalue);
};
Twinkle.config.listDialog.save = function twinkleconfigListDialogSave(button, tbody) {
var result = [];
var current = {};
$(tbody).find('input[type="text"]').each(function(inputkey, input) {
if ($(input).hasClass('twinkle-config-customlist-value')) {
current = { value: input.value };
} else {
current.label = input.value;
// exclude totally empty rows
if (current.value || current.label) {
result.push(current);
}
}
});
$(button).data('value', result);
};
// reset/restore defaults
Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) {
var wantedpref = e.target.id.substring(21); // "twinkle-config-reset-" prefix is stripped
// search tactics
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // continue: skip impossibilities
}
var foundit = false;
$(section.preferences).each(function(prefkey, pref) {
if (pref.name !== wantedpref) {
return true; // continue
}
Twinkle.config.resetPref(pref);
foundit = true;
return false; // break
});
if (foundit) {
return false; // break
}
});
return false; // stop link from scrolling page
};
Twinkle.config.resetPref = function twinkleconfigResetPref(pref) {
switch (pref.type) {
case 'boolean':
document.getElementById(pref.name).checked = Twinkle.defaultConfig[pref.name];
break;
case 'string':
case 'integer':
case 'enum':
document.getElementById(pref.name).value = Twinkle.defaultConfig[pref.name];
break;
case 'set':
$.each(pref.setValues, function(itemkey) {
if (document.getElementById(pref.name + '_' + itemkey)) {
document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].indexOf(itemkey) !== -1;
}
});
break;
case 'customList':
$(document.getElementById(pref.name)).data('value', Twinkle.defaultConfig[pref.name]);
break;
default:
alert('twinkleconfig: unknown data type for preference ' + pref.name);
break;
}
};
Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() {
// no confirmation message - the user can just refresh/close the page to abort
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // continue: skip impossibilities
}
$(section.preferences).each(function(prefkey, pref) {
if (!pref.adminOnly || Morebits.userIsSysop) {
Twinkle.config.resetPref(pref);
}
});
return true;
});
return false; // stop link from scrolling page
};
Twinkle.config.save = function twinkleconfigSave(e) {
Morebits.status.init(document.getElementById('twinkle-config-content'));
var userjs = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user] + ':' + mw.config.get('wgUserName') + '/twinkleoptions.js';
var wikipedia_page = new Morebits.wiki.page(userjs, conv({ hans: '保存参数设置到 ', hant: '儲存偏好設定到 ' }) + userjs);
wikipedia_page.setCallbackParameters(e.target);
wikipedia_page.load(Twinkle.config.writePrefs);
return false;
};
Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
var form = pageobj.getCallbackParameters();
// this is the object which gets serialized into JSON; only
// preferences that this script knows about are kept
var newConfig = {optionsVersion: 2.1};
// a comparison function is needed later on
// it is just enough for our purposes (i.e. comparing strings, numbers, booleans,
// arrays of strings, and arrays of { value, label })
// and it is not very robust: e.g. compare([2], ["2"]) === true, and
// compare({}, {}) === false, but it's good enough for our purposes here
var compare = function(a, b) {
if ($.isArray(a)) {
if (a.length !== b.length) {
return false;
}
var asort = a.sort(), bsort = b.sort();
for (var i = 0; asort[i]; ++i) {
// comparison of the two properties of custom lists
if ((typeof asort[i] === 'object') && (asort[i].label !== bsort[i].label ||
asort[i].value !== bsort[i].value)) {
return false;
} else if (asort[i].toString() !== bsort[i].toString()) {
return false;
}
}
return true;
}
return a === b;
};
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.adminOnly && !Morebits.userIsSysop) {
return; // i.e. "continue" in this context
}
// reach each of the preferences from the form
$(section.preferences).each(function(prefkey, pref) {
var userValue; // = undefined
// only read form values for those prefs that have them
if (!pref.adminOnly || Morebits.userIsSysop) {
if (!section.hidden) {
switch (pref.type) {
case 'boolean': // read from the checkbox
userValue = form[pref.name].checked;
break;
case 'string': // read from the input box or combo box
case 'enum':
userValue = form[pref.name].value;
break;
case 'integer': // read from the input box
userValue = parseInt(form[pref.name].value, 10);
if (isNaN(userValue)) {
Morebits.status.warn(conv({ hans: '保存', hant: '儲存' }), conv({ hans: '您为 ', hant: '您為 ' }) + pref.name + ' 指定的值(' + pref.value + conv({ hans: ')不合法,会继续保存操作,但此值将会跳过。', hant: ')不合法,會繼續儲存操作,但此值將會跳過。' }));
userValue = null;
}
break;
case 'set': // read from the set of check boxes
userValue = [];
if (pref.setDisplayOrder) {
// read only those keys specified in the display order
$.each(pref.setDisplayOrder, function(itemkey, item) {
if (form[pref.name + '_' + item].checked) {
userValue.push(item);
}
});
} else {
// read all the keys in the list of values
$.each(pref.setValues, function(itemkey) {
if (form[pref.name + '_' + itemkey].checked) {
userValue.push(itemkey);
}
});
}
break;
case 'customList': // read from the jQuery data stored on the button object
userValue = $(form[pref.name]).data('value');
break;
default:
alert('twinkleconfig: 未知数据类型,属性 ' + pref.name);
break;
}
} else if (Twinkle.prefs) {
// Retain the hidden preferences that may have customised by the user from twinkleoptions.js
// undefined if not set
userValue = Twinkle.prefs[pref.name];
}
}
// only save those preferences that are *different* from the default
if (userValue !== undefined && !compare(userValue, Twinkle.defaultConfig[pref.name])) {
newConfig[pref.name] = userValue;
}
});
});
var text =
'// <nowiki>\n' +
conv({
hans:
'// twinkleoptions.js:用户Twinkle参数设置文件\n' +
'//\n' +
'// 注:修改您的参数设置最简单的办法是使用\n' +
'// Twinkle参数设置面板,在[[' + Morebits.pageNameNorm + ']]。\n' +
'//\n' +
'// 这个文件是自动生成的,您所做的任何修改(除了\n' +
'// 以一种合法的JavaScript的方式来修改这些属性值)会\n' +
'// 在下一次您点击“保存”时被覆盖。\n' +
'// 修改此文件时,请记得使用合法的JavaScript。\n' +
'\n' +
'window.Twinkle.prefs = ',
hant:
'// twinkleoptions.js:使用者Twinkle參數設定檔案\n' +
'//\n' +
'// 註:修改您的參數設定最簡單的辦法是使用\n' +
'// Twinkle參數設定面板,在[[' + Morebits.pageNameNorm + ']]。\n' +
'//\n' +
'// 這個檔案是自動產生的,您所做的任何修改(除了\n' +
'// 以一種合法的JavaScript的方式來修改這些屬性值)會\n' +
'// 在下一次您點擊「儲存」時被覆蓋。\n' +
'// 修改此檔案時,請記得使用合法的JavaScript。\n' +
'\n' +
'window.Twinkle.prefs = '
});
text += JSON.stringify(newConfig, null, 2);
text +=
';\n' +
'\n' +
conv({ hans: '// twinkleoptions.js到此为止\n', hant: '// twinkleoptions.js到此為止\n' }) +
'// </nowiki>';
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '保存Twinkle参数设置:来自[[', hant: '儲存Twinkle偏好設定:來自[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的自动编辑', hant: ']]的自動編輯' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.save(Twinkle.config.saveSuccess);
};
Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) {
pageobj.getStatusElement().info('成功');
var noticebox = document.createElement('div');
noticebox.className = 'mw-message-box mw-message-box-success';
noticebox.style.fontSize = '100%';
noticebox.style.marginTop = '2em';
noticebox.innerHTML = '<p><b>' + conv({ hans: '您的Twinkle参数设置已被保存。', hant: '您的Twinkle偏好設定已被儲存。' }) + '</b></p><p>' + conv({ hans: '要看到这些更改,您可能需要', hant: '要看到這些更改,您可能需要' }) + '<a href="' + mw.util.getUrl('WP:BYPASS') + '" title="WP:BYPASS"><b>' + conv({ hans: '绕过浏览器缓存', hant: '繞過瀏覽器快取' }) + '</b></a>。</p>';
Morebits.status.root.appendChild(noticebox);
var noticeclear = document.createElement('br');
noticeclear.style.clear = 'both';
Morebits.status.root.appendChild(noticeclear);
};
Twinkle.addInitCallback(Twinkle.config.init);
})(jQuery);
// </nowiki>
2ce62973ad5602d737de174df6929636411cbcff
MediaWiki:Gadget-twinklearv.js
8
151
304
2023-11-06T13:17:04Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklearv.js: ARV module
****************************************
* Mode of invocation: Tab ("ARV")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.arv = function twinklearv() {
var username = Morebits.wiki.flow.relevantUserName(true);
if (!username) {
return;
}
var isIP = mw.util.isIPAddress(username);
var title = isIP ? conv({ hans: '报告IP给管理员', hant: '報告IP給管理員' }) : conv({ hans: '报告用户给管理人员', hant: '報告使用者給管理人員' });
Twinkle.addPortletLink(function() {
Twinkle.arv.callback(username, isIP);
}, conv({ hans: '告状', hant: '告狀' }), 'tw-arv', title);
};
Twinkle.arv.callback = function (uid, isIP) {
if (uid === mw.config.get('wgUserName')) {
alert(conv({ hans: '你不想报告你自己,对吧?', hant: '你不想報告你自己,對吧?' }));
return;
}
var Window = new Morebits.simpleWindow(600, 500);
Window.setTitle(conv({ hans: '报告用户给管理人员', hant: '報告使用者給管理人員' }));
Window.setScriptName('Twinkle');
Window.addFooterLink('VIP', 'WP:VIP');
Window.addFooterLink('EWIP', 'WP:EWIP');
Window.addFooterLink('UAA', 'WP:UAA');
Window.addFooterLink(conv({ hans: '用户名方针', hant: '使用者名稱方針' }), 'WP:U');
Window.addFooterLink('SPI', 'WP:SPI');
Window.addFooterLink(conv({ hans: '告状设置', hant: '告狀設定' }), 'WP:TW/PREF#arv');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'H:TW#告狀');
var form = new Morebits.quickForm(Twinkle.arv.callback.evaluate);
var categories = form.append({
type: 'select',
name: 'category',
label: conv({ hans: '选择报告类型:', hant: '選擇報告類別:' }),
event: Twinkle.arv.callback.changeCategory
});
categories.append({
type: 'option',
label: conv({ hans: '破坏(WP:VIP)', hant: '破壞(WP:VIP)' }),
value: 'aiv'
});
categories.append({
type: 'option',
label: conv({ hans: '编辑争议(WP:EWIP)', hant: '編輯爭議(WP:EWIP)' }),
value: 'ewip'
});
categories.append({
type: 'option',
label: conv({ hans: '用户名(WP:UAA)', hant: '使用者名稱(WP:UAA)' }),
value: 'username',
disabled: mw.util.isIPAddress(uid)
});
categories.append({
type: 'option',
label: conv({ hans: '傀儡调查(WP:SPI)', hant: '傀儡調查(WP:SPI)' }),
value: 'spi'
});
form.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-arv-blockwarning'
});
form.append({
type: 'field',
label: 'Work area',
name: 'work_area'
});
form.append({ type: 'submit', label: '提交' });
form.append({
type: 'hidden',
name: 'uid',
value: uid
});
var result = form.render();
Window.setContent(result);
Window.display();
// Check if the user is blocked, update notice
var query = {
action: 'query',
list: 'blocks',
bkprop: 'range|flags',
format: 'json'
};
if (isIP) {
query.bkip = uid;
} else {
query.bkusers = uid;
}
new Morebits.wiki.api(conv({ hans: '检查用户的封禁状态', hant: '檢查使用者的封鎖狀態' }), query, function (apiobj) {
var blocklist = apiobj.getResponse().query.blocks;
if (blocklist.length) {
var block = blocklist[0];
var message = (isIP ? conv({ hans: '此IP地址', hant: '此IP位址' }) : conv({ hans: '此账户', hant: '此帳號' })) + conv({ hans: '已经被', hant: '已經被' }) + (block.partial ? '部分' : '');
// Start and end differ, range blocked
message += block.rangestart !== block.rangeend ? conv({ hans: '段封禁。', hant: '段封鎖。' }) : conv({ hans: '封禁。', hant: '封鎖。' });
if (block.partial) {
$('#twinkle-arv-blockwarning').css('color', 'black'); // Less severe
}
$('#twinkle-arv-blockwarning').text(message);
}
}).post();
// We must init the
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.category.dispatchEvent(evt);
};
Twinkle.arv.lta_list = [
{ value: '', label: conv({ hans: '请选择', hant: '請選擇' }) },
{ value: 'Adam Asrul', label: 'Adam Asrul、ADAM' },
{ value: 'Albert20009', label: 'Albert20009' },
{ value: 'Kapol6360', label: 'Kapol6360、Kapol' },
{ value: 'R1t5', label: conv({ hans: '114.27、数论和人瑞类条目破坏、R1t5', hant: '114.27、數論和人瑞類條目破壞、R1t5' }) },
{ value: 'Royalfanta', label: 'Royalfanta、RF' },
{ value: 'Xayahrainie43', label: 'Xayahrainie43、X43、妍欣' },
{ value: '米記123', label: '米記123' }
];
Twinkle.arv.callback.pick_lta = function twinklearvCallbackPickLta(e) {
e.target.form.sockmaster.value = e.target.value;
Twinkle.arv.callback.spi_notice(e.target.form, e.target.value);
Twinkle.arv.callback.set_sockmaster(e.target.value);
e.target.value = '';
};
Twinkle.arv.callback.sockmaster_changed = function twinklearvCallbackSockmasterChanged(e) {
Twinkle.arv.callback.spi_notice(e.target.form, e.target.value);
Twinkle.arv.callback.set_sockmaster(e.target.value);
};
Twinkle.arv.callback.spi_notice = function twinklearvCallbackSpiNotice(form, sockmaster) {
var previewText = '{{#ifexist:Wikipedia:傀儡調查/案件/' + sockmaster +
'|{{#ifexist:Wikipedia:傀儡調查/案件通告/' + sockmaster +
' |<div class="extendedconfirmed-show sysop-show">{{Memo|1={{Wikipedia:傀儡調查/案件通告/' + sockmaster + '}}|2=notice}}</div>' +
' |無案件通告}}' +
'|您將建立新的提報頁面,如果您希望提報過往曾被提報過的使用者,請檢查您的輸入是否正確。}}';
form.spinoticepreviewer.beginRender(previewText, 'Wikipedia:傀儡調查/案件/' + sockmaster);
};
Twinkle.arv.callback.set_sockmaster = function twinklearvCallbackSetSockmaster(sockmaster) {
$('code.tw-arv-sockmaster').text('{{subst:Socksuspectnotice|1=' + sockmaster + '}}');
};
Twinkle.arv.callback.changeCategory = function (e) {
var value = e.target.value;
var root = e.target.form;
var old_area = Morebits.quickForm.getElements(root, 'work_area')[0];
var work_area = null;
var previewlink = document.createElement('a');
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
$(previewlink).on('click', function() {
Twinkle.arv.callback.preview(root);
});
switch (value) {
case 'aiv':
/* falls through */
default:
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告用户破坏', hant: '報告使用者破壞' }),
name: 'work_area'
});
work_area.append({
type: 'div',
label: conv({ hans: '提报傀儡应优先发送至傀儡调查,除非相关的账户有高频率、涉及多个页面等紧急严重的破坏行为。', hant: '提報傀儡應優先發送至傀儡調查,除非相關的帳號有高頻率、涉及多個頁面等緊急嚴重的破壞行為。' })
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '相关页面:', hant: '相關頁面:' }),
tooltip: conv({ hans: '如不希望让报告链接到页面,请留空', hant: '如不希望讓報告連結到頁面,請留空' }),
value: mw.util.getParamValue('vanarticle') || '',
event: function(e) {
var value = e.target.value;
var root = e.target.form;
if (value === '') {
root.badid.disabled = root.goodid.disabled = true;
} else {
root.badid.disabled = false;
root.goodid.disabled = root.badid.value === '';
}
}
});
work_area.append({
type: 'input',
name: 'badid',
label: conv({ hans: '受到破坏的修订版本:', hant: '受到破壞的修訂版本:' }),
tooltip: conv({ hans: '留空以略过差异', hant: '留空以略過差異' }),
value: mw.util.getParamValue('vanarticlerevid') || '',
disabled: !mw.util.getParamValue('vanarticle'),
event: function(e) {
var value = e.target.value;
var root = e.target.form;
root.goodid.disabled = value === '';
}
});
work_area.append({
type: 'input',
name: 'goodid',
label: conv({ hans: '破坏前的修订版本:', hant: '破壞前的修訂版本:' }),
tooltip: conv({ hans: '留空以略过差异的较早版本', hant: '留空以略過差異的較早版本' }),
value: mw.util.getParamValue('vanarticlegoodrevid') || '',
disabled: !mw.util.getParamValue('vanarticle') || mw.util.getParamValue('vanarticlerevid')
});
work_area.append({
type: 'checkbox',
name: 'arvtype',
list: [
{
label: conv({ hans: '已发出最后(层级4或4im)警告', hant: '已發出最後(層級4或4im)警告' }),
value: 'final'
},
{
label: conv({ hans: '封禁过期后随即破坏', hant: '封鎖過期後隨即破壞' }),
value: 'postblock'
},
{
label: conv({ hans: '显而易见的纯破坏用户', hant: '顯而易見的純破壞使用者' }),
value: 'vandalonly',
disabled: mw.util.isIPAddress(root.uid.value)
},
{
label: conv({ hans: '显而易见的spambot或失窃账户', hant: '顯而易見的spambot或失竊帳號' }),
value: 'spambot'
},
{
label: conv({ hans: '仅用来散发广告宣传的用户', hant: '僅用來散發廣告宣傳的使用者' }),
value: 'promoonly',
disabled: mw.util.isIPAddress(root.uid.value)
}
]
});
if (!mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName(true))) {
work_area.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '在页面上及编辑摘要隐藏用户名', hant: '在頁面上及編輯摘要隱藏使用者名稱' }),
tooltip: conv({ hans: '若用户名不当请勾选此项,注意:请考虑私下联系管理员处理。', hant: '若使用者名稱不當請勾選此項,注意:請考慮私下聯絡管理員處理。' }),
name: 'hidename',
value: 'hidename'
}
]
});
}
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'ewip':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告编辑争议', hant: '報告編輯爭議' }),
name: 'work_area'
});
work_area.append(
{
type: 'dyninput',
name: 'page',
label: conv({ hans: '相关页面:', hant: '相關頁面:' }),
sublabel: conv({ hans: '页面:', hant: '頁面:' }),
tooltip: conv({ hans: '如不希望让报告链接到页面,请留空', hant: '如不希望讓報告連結到頁面,請留空' }),
min: 1,
max: 10
});
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'username':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告不当用户名', hant: '報告不當使用者名稱' }),
name: 'work_area'
});
work_area.append({
type: 'header',
label: conv({ hans: '不当用户名类型', hant: '不當使用者名稱類別' }),
tooltip: conv({
hans: '维基百科不允许使用带有误导性、宣传性、侮辱性或破坏性的用户名。此外,使用域名及邮箱地址的用户名亦被禁止。这些准则俱应应用至用户名及签名。在其他语言中不当的用户名或通过错拼、替代、暗示、拆字或任何间接方法达成的非妥当用户名同样视为违规。', hant:
'維基百科不允許使用帶有誤導性、宣傳性、侮辱性或破壞性的使用者名稱。此外,使用域名及電子信箱位址的使用者名稱亦被禁止。這些準則俱應應用至使用者名稱及簽名。在其他語言中不當的使用者名稱或通過錯拼、替代、暗示、拆字或任何間接方法達成的非妥當使用者名稱同樣視為違規。'
})
});
work_area.append({
type: 'checkbox',
name: 'arvtype',
list: [
{
label: conv({ hans: '误导性用户名', hant: '誤導性使用者名稱' }),
value: conv({ hans: '误导性', hant: '誤導性' }),
tooltip: conv({
hans: '误导性用户名隐含着与贡献者相关或误导他人的事情。例如︰不实观点、暗示账户拥有特定权限或暗示该账户并非由一人拥有而是由一个组群、一个项目或一个集体运作。', hant:
'誤導性使用者名稱隱含著與貢獻者相關或誤導他人的事情。例如︰不實觀點、暗示帳戶擁有特定權限或暗示該帳戶並非由一人擁有而是由一個群組、一個計畫或一個集體運作。'
})
},
{
label: conv({ hans: '宣传性用户名', hant: '宣傳性使用者名稱' }),
value: conv({ hans: '宣传性', hant: '宣傳性' }),
tooltip: conv({ hans: '宣传性用户名会于维基百科上起推销一个组群或一间公司的作用。', hant: '宣傳性使用者名稱會於維基百科上起推銷一個群組或一間公司的作用。' })
},
{
label: conv({ hans: '暗示并非由一人拥有', hant: '暗示並非由一人擁有' }),
value: 'shared',
tooltip: conv({ hans: '每个维基账户只可以代表个人(容许一些例外情况),所有与他人分享账户的行为(包括分享账户密码)均被禁止。', hant: '每個維基帳戶只可以代表個人(容許一些例外情況),所有與他人分享帳戶的行為(包括分享帳戶密碼)均被禁止。' })
},
{
label: conv({ hans: '侮辱性用户名', hant: '侮辱性使用者名稱' }),
value: '侮辱性',
tooltip: conv({ hans: '侮辱性用户名令协调编辑变得困难,甚至无可能。', hant: '侮辱性使用者名稱令協調編輯變得困難,甚至無可能。' })
},
{
label: conv({ hans: '破坏性用户名', hant: '破壞性使用者名稱' }),
value: conv({ hans: '破坏性', hant: '破壞性' }),
tooltip: conv({ hans: '破坏性用户名包括人身攻击、伪冒他人或其他一切有着清晰可见的破坏维基百科意图的用户名。', hant: '破壞性使用者名稱包括人身攻擊、偽冒他人或其他一切有著清晰可見的破壞維基百科意圖的使用者名稱。' })
}
]
});
work_area.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '在页面上隐藏用户名(需监督的用户名请勿于站内报告,勾选此项并不构成能在站内报告的理由)', hant: '在頁面上隱藏使用者名稱(需監督的使用者名稱請勿於站內報告,勾選此項並不構成能在站內報告的理由)' }),
tooltip: conv({ hans: '若用户名不当请勾选此项,注意:请考虑私下联系管理员处理。', hant: '若使用者名稱不當請勾選此項,注意:請考慮私下聯絡管理員處理。' }),
name: 'hidename',
value: 'hidename'
}
],
style: 'font-weight: bold;'
});
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'spi':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '发起傀儡调查', hant: '發起傀儡調查' }),
name: 'work_area'
});
work_area.append({
type: 'select',
name: 'common_lta',
label: '持續出沒的破壞者:',
style: 'width: 420px;',
list: Twinkle.arv.lta_list,
event: Twinkle.arv.callback.pick_lta
});
work_area.append({
type: 'input',
name: 'sockmaster',
label: $('<a>', {
href: mw.util.getUrl('Special:PrefixIndex/Wikipedia:傀儡調查/案件/'),
text: 'Wikipedia:傀儡調查/案件/',
target: '_blank'
})[0],
tooltip: conv({ hans: '主账户的用户名(不含User:前缀),这被用于创建傀儡调查子页面的标题,可在 Wikipedia:傀儡调查/案件 的子页面搜索先前的调查。', hant: '主帳號的使用者名稱(不含User:字首),這被用於建立傀儡調查子頁面的標題,可在 Wikipedia:傀儡調查/案件 的子頁面搜尋先前的調查。' }),
value: root.uid.value,
event: Twinkle.arv.callback.sockmaster_changed
});
work_area.append({ type: 'div', id: 'twinklearv-spinoticebox', style: 'display: none' });
work_area.append({
type: 'dyninput',
name: 'sockpuppet',
label: '傀儡',
sublabel: '傀儡:',
tooltip: conv({ hans: '傀儡的用户名(不含User:前缀)', hant: '傀儡的使用者名稱(不含User:字首)' }),
min: 2,
max: 9
});
work_area.append({
type: 'textarea',
label: conv({ hans: '证据:', hant: '證據:' }),
name: 'reason',
tooltip: conv({ hans: '输入能够用来体现这些用户可能滥用多重账户的证据,这通常包括互助客栈发言、页面历史或其他有关的信息。请避免在此处提供非与傀儡或滥用多重账户相关的其他讨论。', hant: '輸入能夠用來體現這些使用者可能濫用多重帳號的證據,這通常包括互助客棧發言、頁面歷史或其他有關的資訊。請避免在此處提供非與傀儡或濫用多重帳號相關的其他討論。' })
});
work_area.append({
type: 'checkbox',
list: [{
label: conv({ hans: '请求用户查核', hant: '請求使用者查核' }),
name: 'checkuser',
tooltip: conv({ hans: '用户查核是一种用于获取傀儡指控相关技术证据的工具,若没有正当理由则不会使用,您必须在证据字段充分解释为什么需要使用该工具。用户查核不会用于公开连接用户账户使用的IP地址。', hant: '使用者查核是一種用於獲取傀儡指控相關技術證據的工具,若沒有正當理由則不會使用,您必須在證據欄位充分解釋為什麼需要使用該工具。使用者查核不會用於公開連接使用者帳號使用的IP位址。' })
}]
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area.append({
type: 'div',
label: [
conv({ hans: '请使用常识决定是否以', hant: '請使用常識決定是否以' }),
$('<code>').addClass('tw-arv-sockmaster').attr('style', 'margin: 2px;')[0],
conv({ hans: '通知用户。这不是必须的,对于涉及新用户的报告而言,通知他们能让报告显得更公平,但是许多情况下(如长期破坏者)通知更可能适得其反。', hant: '通知使用者。這不是必須的,對於涉及新使用者的報告而言,通知他們能讓報告顯得更公平,但是許多情況下(如長期破壞者)通知更可能適得其反。' })
]
});
work_area = work_area.render();
$('input:text[name=sockpuppet]', work_area).first().val(root.uid.value);
old_area.parentNode.replaceChild(work_area, old_area);
root.spinoticepreviewer = new Morebits.wiki.preview($(work_area).find('#twinklearv-spinoticebox').last()[0]);
Twinkle.arv.callback.spi_notice(root, root.uid.value);
Twinkle.arv.callback.set_sockmaster(root.uid.value);
break;
}
root.previewer = new Morebits.wiki.preview($(work_area).find('#twinklearv-previewbox').last()[0]);
};
Twinkle.arv.callback.preview = function(form) {
var reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
var input = Morebits.quickForm.getInputData(form);
var title;
switch (input.category) {
case 'vip': title = 'Wikipedia:当前的破坏'; break;
case 'ewip': title = 'Wikipedia:管理员布告板/编辑争议'; break;
case 'username': title = 'Wikipedia:管理员布告板/不当用户名'; break;
case 'spi': title = 'Wikipedia:傀儡調查/案件/' + input.sockmaster; break;
default: title = mw.config.get('wgPageName'); break;
}
form.previewer.beginRender('__NOTOC__' + reason[0], title);
};
Twinkle.arv.callback.getReportWikitext = function(form) {
var input = Morebits.quickForm.getInputData(form);
var reason = '';
var comment = '';
var uid = input.uid;
var checkTitle = function(title, revid) {
if (/https?:\/\//.test(title)) {
alert(conv({ hans: '页面名称不能使用网址。', hant: '頁面名稱不能使用網址。' }));
return false;
}
var page;
try {
page = new mw.Title(title);
} catch (error) {
alert(conv({ hans: '“', hant: '「' }) + title + conv({ hans: '”不是一个有效的页面名称,如要使用差异链接请放在“评论”', hant: '」不是一個有效的頁面名稱,如要使用差異連結請放在「評論」' }) + (revid ? conv({ hans: ',或正确输入“修订版本”', hant: ',或正確輸入「修訂版本」' }) : '') + '。');
return false;
}
if (page.namespace === -1) {
alert(conv({ hans: '“', hant: '「' }) + title + conv({ hans: '”属于特殊页面,如要使用差异链接请放在“评论”', hant: '」屬於特殊頁面,如要使用差異連結請放在「評論」' }) + (revid ? conv({ hans: ',或正确输入“修订版本”', hant: ',或正確輸入「修訂版本」' }) : '') + '。');
return false;
}
return page;
};
var page;
switch (input.category) {
// Report user for vandalism
case 'aiv':
/* falls through */
default:
if (!input.arvtype.length && input.reason === '') {
alert(conv({ hans: '您必须指定理由', hant: '您必須指定理由' }));
return;
}
reason += '=== ' + (input.hidename ? conv({ hans: '已隐藏用户名', hant: '已隱藏使用者名稱' }) : uid) + ' ===\n';
reason += "* '''{{vandal|" + (/=/.test(uid) ? '1=' : '') + uid;
if (input.hidename) {
reason += '|hidename=1';
}
reason += "}}'''\n";
var types = input.arvtype.map(function(v) {
switch (v) {
case 'final':
return '已发出最后警告';
case 'postblock':
return '封禁过期后随即破坏';
case 'spambot':
return '显而易见的spambot或失窃账户';
case 'vandalonly':
return '显而易见的纯破坏用户';
case 'promoonly':
return '仅用来散发广告宣传的用户';
default:
return '未知理由';
}
}).join(',');
if (input.page !== '') {
page = checkTitle(input.page, true);
if (!page) {
return;
}
comment += '* {{pagelinks|' + (page.getPrefixedText().indexOf('=') > -1 ? '1=' : '') + page.getPrefixedText() + '}}';
if (input.badid) {
comment += '({{diff|' + page.getPrefixedText() + '|' + input.badid + '|' + (input.goodid ? input.goodid : '') + '|diff}})';
}
comment += '\n';
}
if (types) {
comment += '* ' + types;
}
if (input.reason !== '') {
input.reason = input.reason.replace(/\n\n+/g, '\n');
input.reason = input.reason.replace(/\r?\n/g, '\n*:'); // indent newlines
comment += (types ? '。' : '* ') + input.reason;
}
comment = comment.trim();
comment = Morebits.string.appendPunctuation(comment);
reason += comment + '\n* 发现人:~~~~\n* 处理:';
break;
// Report 3RR
case 'ewip':
if (input.reason === '') {
alert(conv({ hans: '您必须指定理由', hant: '您必須指定理由' }));
return;
}
reason += '=== ' + uid + ' ===\n';
reason += "* '''{{vandal|" + (/=/.test(uid) ? '1=' : '') + uid + "}}'''\n";
var pages = $.map($('input:text[name=page]', form), function (o) {
return $(o).val() || null;
});
for (var i = 0; i < pages.length; i++) {
page = checkTitle(pages[i], false);
if (!page) {
return;
}
comment += '* {{pagelinks|' + (page.getPrefixedText().indexOf('=') > -1 ? '1=' : '') + page.getPrefixedText() + '}}\n';
}
input.reason = input.reason.replace(/\n\n+/g, '\n');
input.reason = input.reason.replace(/\r?\n/g, '\n*:'); // indent newlines
comment += '* ' + input.reason + '\n';
comment = comment.trim();
comment = Morebits.string.appendPunctuation(comment);
reason += comment + '\n* 提報人:~~~~\n* 处理:';
break;
// Report inappropriate username
case 'username':
types = input.arvtype.map(Morebits.string.toLowerCaseFirstChar);
var hasShared = types.indexOf('shared') > -1;
if (hasShared) {
types.splice(types.indexOf('shared'), 1);
}
if (types.indexOf('侮辱性') !== -1) {
if (!confirm(conv({
hans: '警告:严重的侮辱性用户名和针对特定个人的侮辱性用户名不应在公开页面报告,而是应当私下联系监督员处理。是否继续?', hant:
'警告:嚴重的侮辱性使用者名稱和針對特定個人的侮辱性使用者名稱不應在公開頁面報告,而是應當私下聯絡監督員處理。是否繼續?'
}))) {
return;
}
}
if (types.length <= 2) {
types = types.join('和');
} else {
types = [ types.slice(0, -1).join('、'), types.slice(-1) ].join('和');
}
comment += '*{{user-uaa|1=' + uid;
if (input.hidename) {
comment += '|hidename=1';
}
comment += '}} – ';
if (types.length) {
comment += types + conv({ hans: '用户名', hant: '使用者名稱' });
}
if (types.length && hasShared) {
comment += ',';
}
if (hasShared) {
comment += conv({ hans: '暗示该账户并非由一人拥有', hant: '暗示該帳號並非由一人擁有' });
}
if (types.length || hasShared) {
comment += '。';
}
if (input.reason) {
comment += Morebits.string.toUpperCaseFirstChar(input.reason);
}
comment = Morebits.string.appendPunctuation(comment);
comment += '--~~~~';
comment = comment.replace(/\r?\n/g, '\n*:'); // indent newlines
reason = comment;
break;
// WP:SPI
case 'spi':
if (!input.reason) {
alert(conv({ hans: '请输入证据。', hant: '請輸入證據。' }));
return;
}
var sockpuppets = Morebits.array.uniq($.map($('input:text[name=sockpuppet]', form), function(o) {
return $(o).val().trim() || null;
}));
if (!sockpuppets[0]) {
alert(conv({ hans: '您没有指定任何傀儡。', hant: '您沒有指定任何傀儡。' }));
return;
}
comment += '{{subst:SPI report|';
if (sockpuppets.indexOf(input.sockmaster) === -1) {
comment += '1={{subst:#ifexist:{{subst:FULLPAGENAME}}||' + input.sockmaster + '}}|';
}
comment += sockpuppets.map(function(sock, index) {
return (index + 2) + '=' + sock;
}).join('|') + '\n|evidence=' + Morebits.string.appendPunctuation(input.reason) + '\n';
if (input.checkuser) {
comment += '|checkuser=yes';
}
comment += '}}';
reason = comment;
break;
}
return [reason, comment];
};
Twinkle.arv.callback.evaluate = function(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
var uid = input.uid;
var reason;
var summary;
switch (input.category) {
// Report user for vandalism
case 'aiv':
/* falls through */
default:
reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
summary = conv({ hans: '报告', hant: '報告' }) + '[[Special:Contributions/' + uid + '|' + uid + ']]';
if (input.hidename) {
summary = conv({ hans: '报告一名用户', hant: '報告一名使用者' });
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:当前的破坏';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var aivPage = new Morebits.wiki.page('Wikipedia:当前的破坏', conv({ hans: '处理VIP请求', hant: '處理VIP請求' }));
aivPage.setFollowRedirect(true);
aivPage.load(function() {
var text = aivPage.getPageText();
var $aivLink = '<a target="_blank" href="/wiki/WP:VIP">WP:VIP</a>';
// check if user has already been reported
if (new RegExp('===\\s*\\{\\{\\s*(?:[Vv]andal)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}\\s*===').test(text)) {
aivPage.getStatusElement().error(conv({ hans: '报告已存在,将不会加入新的', hant: '報告已存在,將不會加入新的' }));
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其加入到', hant: '您輸入的評論已在下方提供,您可以將其加入到' }) + $aivLink + conv({ hans: '已存在的小节中:', hant: '已存在的小節中:' }));
return;
}
aivPage.setPageSection(0);
aivPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
aivPage.setEditSummary(summary);
aivPage.setChangeTags(Twinkle.changeTags);
aivPage.setAppendText('\n' + reason[0]);
aivPage.append();
});
break;
// Report 3RR
case 'ewip':
reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
summary = conv({ hans: '报告', hant: '報告' }) + '[[Special:Contributions/' + uid + '|' + uid + ']]';
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:管理员布告板/编辑争议';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var ewipPage = new Morebits.wiki.page('Wikipedia:管理员布告板/编辑争议', conv({ hans: '处理EWIP请求', hant: '處理EWIP請求' }));
ewipPage.setFollowRedirect(true);
ewipPage.load(function() {
var text = ewipPage.getPageText();
var $ewipLink = '<a target="_blank" href="/wiki/WP:EWIP">WP:EWIP</a>';
// check if user has already been reported
if (new RegExp('===\\s*\\{\\{\\s*(?:[Vv]andal)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}\\s*===').test(text)) {
ewipPage.getStatusElement().error(conv({ hans: '报告已存在,将不会加入新的', hant: '報告已存在,將不會加入新的' }));
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其加入到', hant: '您輸入的評論已在下方提供,您可以將其加入到' }) + $ewipLink + conv({ hans: '已存在的小节中:', hant: '已存在的小節中:' }));
return;
}
ewipPage.setPageSection(0);
ewipPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
ewipPage.setEditSummary(summary);
ewipPage.setChangeTags(Twinkle.changeTags);
ewipPage.setAppendText('\n' + reason[0]);
ewipPage.append();
});
break;
// Report inappropriate username
case 'username':
reason = Twinkle.arv.callback.getReportWikitext(form);
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:管理员布告板/不当用户名';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var uaaPage = new Morebits.wiki.page('Wikipedia:管理员布告板/不当用户名', conv({ hans: '处理UAA请求', hant: '處理UAA請求' }));
uaaPage.setFollowRedirect(true);
uaaPage.load(function() {
var text = uaaPage.getPageText();
// check if user has already been reported
if (new RegExp('\\{\\{\\s*user-uaa\\s*\\|\\s*(1\\s*=\\s*)?' + Morebits.string.escapeRegExp(uid) + '\\s*(\\||\\})').test(text)) {
uaaPage.getStatusElement().error(conv({ hans: '用户已被列入。', hant: '使用者已被列入。' }));
var $uaaLink = '<a target="_blank" href="/wiki/WP:UAA">WP:UAA</a>';
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其手工加入', hant: '您輸入的評論已在下方提供,您可以將其手工加入' }) + $uaaLink + conv({ hans: '上该用户的报告中:', hant: '上該使用者的報告中:' }));
return;
}
uaaPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
uaaPage.setEditSummary(conv({ hans: '新提报', hant: '新提報' }));
uaaPage.setChangeTags(Twinkle.changeTags);
uaaPage.setAppendText('\n\n' + reason[0]);
uaaPage.append();
});
break;
// WP:SPI
case 'spi':
reason = Twinkle.arv.callback.getReportWikitext(form);
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var reportpage = 'Wikipedia:傀儡調查/案件/' + input.sockmaster;
Morebits.wiki.actionCompleted.redirect = reportpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var spiPage = new Morebits.wiki.page(reportpage, conv({ hans: '抓取讨论页面', hant: '抓取討論頁面' }));
spiPage.setFollowRedirect(true);
spiPage.setEditSummary(conv({ hans: '加入新提报', hant: '加入新提報' }));
spiPage.setChangeTags(Twinkle.changeTags);
spiPage.setAppendText(reason[0]);
spiPage.setWatchlist(Twinkle.getPref('spiWatchReport'));
spiPage.append();
break;
}
};
Twinkle.addInitCallback(Twinkle.arv, 'arv');
})(jQuery);
// </nowiki>
f2d42199b9b3c6ccc713a10d99a13654c2695474
MediaWiki:Gadget-twinklebatchdelete.js
8
166
334
2023-11-06T13:17:07Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklebatchdelete.js: Batch delete module (sysops only)
****************************************
* Mode of invocation: Tab ("D-batch")
* Active on: Existing non-articles, and Special:PrefixIndex
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.batchdelete = function twinklebatchdelete() {
if (
Morebits.userIsSysop && (
(mw.config.get('wgCurRevisionId') && mw.config.get('wgNamespaceNumber') > 0) ||
mw.config.get('wgCanonicalSpecialPageName') === 'Prefixindex' ||
mw.config.get('wgCanonicalSpecialPageName') === 'BrokenRedirects'
)
) {
Twinkle.addPortletLink(Twinkle.batchdelete.callback, conv({ hans: '批删', hant: '批刪' }), 'tw-batch', conv({ hans: '删除此分类或页面中的所有链接', hant: '刪除此分類或頁面中的所有連結' }));
}
};
Twinkle.batchdelete.unlinkCache = {};
// Has the subpages list been loaded?
var subpagesLoaded;
Twinkle.batchdelete.callback = function twinklebatchdeleteCallback() {
subpagesLoaded = false;
var Window = new Morebits.simpleWindow(600, 400);
Window.setTitle(conv({ hans: '批量删除', hant: '批次刪除' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#batchdelete');
var form = new Morebits.quickForm(Twinkle.batchdelete.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除页面', hant: '刪除頁面' }),
name: 'delete_page',
value: 'delete',
checked: true,
subgroup: {
type: 'checkbox',
list: [
{
label: conv({ hans: '删除关联的讨论页(用户讨论页除外)', hant: '刪除關聯的討論頁(使用者討論頁除外)' }),
name: 'delete_talk',
value: 'delete_talk',
checked: true
},
{
label: conv({ hans: '删除到已删页面的重定向页', hant: '刪除到已刪頁面的重新導向頁面' }),
name: 'delete_redirects',
value: 'delete_redirects',
checked: true
},
{
label: conv({ hans: '删除已删页面的子页面', hant: '刪除已刪頁面的子頁面' }),
name: 'delete_subpages',
value: 'delete_subpages',
checked: false,
event: Twinkle.batchdelete.callback.toggleSubpages,
subgroup: {
type: 'checkbox',
list: [
{
label: conv({ hans: '删除已删子页面的讨论页', hant: '刪除已刪子頁面的討論頁' }),
name: 'delete_subpage_talks',
value: 'delete_subpage_talks'
},
{
label: conv({ hans: '删除到已删子页面的重定向页', hant: '刪除到已刪子頁面的重新導向頁面' }),
name: 'delete_subpage_redirects',
value: 'delete_subpage_redirects'
},
{
label: conv({ hans: '取消所有已删页面的链入(仅处理条目及Portal命名空间)', hant: '取消所有已刪頁面的連入(僅處理條目及Portal命名空間)' }),
name: 'unlink_subpages',
value: 'unlink_subpages'
}
]
}
}
]
}
},
{
label: conv({ hans: '取消链入(仅处理条目及Portal命名空间)', hant: '取消連入(僅處理條目及Portal命名空間)' }),
name: 'unlink_page',
value: 'unlink',
checked: false
},
{
label: conv({ hans: '移除文件使用(所有命名空间)', hant: '移除檔案使用(所有命名空間)' }),
name: 'unlink_file',
value: 'unlink_file',
checked: true
}
]
});
form.append({
type: 'select',
name: 'common_reason',
label: '常用理由:',
style: 'width: 85%;',
list: Twinkle.batchdelete.deletereasonlist,
event: Twinkle.batchdelete.callback.change_common_reason
});
form.append({
name: 'reason',
type: 'input',
label: '理由:',
size: 75
});
var query = {
action: 'query',
prop: 'revisions|info|imageinfo',
inprop: 'protection',
rvprop: 'size|user'
};
// On categories
if (mw.config.get('wgNamespaceNumber') === 14) {
query.generator = 'categorymembers';
query.gcmtitle = mw.config.get('wgPageName');
query.gcmlimit = Twinkle.getPref('batchMax');
// On Special:PrefixIndex
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'Prefixindex') {
query.generator = 'allpages';
query.gaplimit = Twinkle.getPref('batchMax');
if (mw.util.getParamValue('prefix')) {
query.gapnamespace = mw.util.getParamValue('namespace');
query.gapprefix = mw.util.getParamValue('prefix');
} else {
var pathSplit = decodeURIComponent(location.pathname).split('/');
if (pathSplit.length < 3 || pathSplit[2] !== 'Special:前缀索引') {
return;
}
var titleSplit = pathSplit[3].split(':');
query.gapnamespace = mw.config.get('wgNamespaceIds')[titleSplit[0].toLowerCase()];
if (titleSplit.length < 2 || typeof query.gapnamespace === 'undefined') {
query.gapnamespace = 0; // article namespace
query.gapprefix = pathSplit.splice(3).join('/');
} else {
pathSplit = pathSplit.splice(4);
pathSplit.splice(0, 0, titleSplit.splice(1).join(':'));
query.gapprefix = pathSplit.join('/');
}
}
// On Special:BrokenRedirects
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'BrokenRedirects') {
query.generator = 'querypage';
query.gqppage = 'BrokenRedirects';
query.gqplimit = Twinkle.getPref('batchMax');
// On normal pages
} else {
query.generator = 'links';
query.titles = mw.config.get('wgPageName');
query.gpllimit = Twinkle.getPref('batchMax');
}
var statusdiv = document.createElement('div');
statusdiv.style.padding = '15px'; // just so it doesn't look broken
Window.setContent(statusdiv);
Morebits.status.init(statusdiv);
Window.display();
Twinkle.batchdelete.pages = {};
var statelem = new Morebits.status(conv({ hans: '抓取页面列表', hant: '抓取頁面列表' }));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '加载中…', hant: '載入中…' }), query, function (apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page').filter(':not([missing])'); // :not([imagerepository="shared"])
$pages.each(function(index, page) {
var $page = $(page);
var ns = $page.attr('ns');
var title = $page.attr('title');
var isRedir = $page.attr('redirect') === '';
var $editprot = $page.find('pr[type="edit"][level="sysop"]');
var isProtected = $editprot.length > 0;
var size = $page.find('rev').attr('size');
var metadata = [];
if (isRedir) {
metadata.push(conv({ hans: '重定向', hant: '重新導向' }));
}
if (isProtected) {
metadata.push(conv({ hans: '全保护,', hant: '全保護,' }) +
($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)') + conv({ hans: '过期', hant: '過期' }));
}
if (ns === '6') { // mimic what delimages used to show for files
metadata.push(conv({ hans: '上传者:', hant: '上傳者:' }) + $page.find('ii').attr('user'));
metadata.push(conv({ hans: '最后编辑:', hant: '最後編輯:' }) + $page.find('rev').attr('user'));
} else {
metadata.push(mw.language.convertNumber(size) + conv({ hans: '字节', hant: '位元組' }));
}
Twinkle.batchdelete.pages[title] = {
label: title + (metadata.length ? '(' + metadata.join(',') + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
};
});
var form = apiobj.params.form;
form.append({ type: 'header', label: conv({ hans: '待删除页面', hant: '待刪除頁面' }) });
form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function dBatchSelectAll() {
$(result).find('input[name=pages]:not(:checked)').each(function(_, e) {
e.click(); // check it, and invoke click event so that subgroup can be shown
});
// Check any unchecked subpages too
$('input[name="pages.subpages"]').prop('checked', true);
}
});
form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function dBatchDeselectAll() {
$(result).find('input[name=pages]:checked').each(function(_, e) {
e.click(); // uncheck it, and invoke click event so that subgroup can be hidden
});
}
});
form.append({
type: 'checkbox',
name: 'pages',
id: 'tw-dbatch-pages',
shiftClickSupport: true,
list: $.map(Twinkle.batchdelete.pages, function (e) {
return e;
})
});
form.append({ type: 'submit' });
var result = form.render();
apiobj.params.Window.setContent(result);
Morebits.quickForm.getElements(result, 'pages').forEach(generateArrowLinks);
}, statelem);
wikipedia_api.params = { form: form, Window: Window };
wikipedia_api.post();
};
function generateArrowLinks (checkbox) {
var link = Morebits.htmlNode('a', ' >');
link.setAttribute('class', 'tw-dbatch-page-link');
link.setAttribute('href', mw.util.getUrl(checkbox.value));
link.setAttribute('target', '_blank');
checkbox.nextElementSibling.append(link);
}
Twinkle.batchdelete.generateNewPageList = function(form) {
// Update the list of checked pages in Twinkle.batchdelete.pages object
var elements = form.elements.pages;
if (elements instanceof NodeList) { // if there are multiple pages
for (var i = 0; i < elements.length; ++i) {
Twinkle.batchdelete.pages[elements[i].value].checked = elements[i].checked;
}
} else if (elements instanceof HTMLInputElement) { // if there is just one page
Twinkle.batchdelete.pages[elements.value].checked = elements.checked;
}
return new Morebits.quickForm.element({
type: 'checkbox',
name: 'pages',
id: 'tw-dbatch-pages',
shiftClickSupport: true,
list: $.map(Twinkle.batchdelete.pages, function (e) {
return e;
})
}).render();
};
Twinkle.batchdelete.deletereasonlist = [
{
label: conv({ hans: '请选择', hant: '請選擇' }),
value: ''
},
{
label: conv({ hans: 'G10: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: 'G10: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' }),
value: conv({ hans: '[[Wikipedia:CSD#G10|G10]]: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: '[[Wikipedia:CSD#G10|G10]]: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' })
},
{
label: conv({ hans: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等', hant: 'G15: 孤立頁面,比如沒有主頁面的討論頁、指向空頁面的重新導向等' }),
value: conv({ hans: '[[Wikipedia:CSD#G15|G15]]: 孤立页面', hant: '[[Wikipedia:CSD#G15|G15]]: 孤立頁面' })
},
{
label: conv({ hans: 'F6: 没有被条目使用的非自由著作权文件', hant: 'F6: 沒有被條目使用的非自由著作權檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F6|F6]]: 没有被条目使用的[[Wikipedia:合理使用|非自由著作权]]文件', hant: '[[Wikipedia:CSD#F6|F6]]: 沒有被條目使用的[[Wikipedia:合理使用|非自由著作權]]檔案' })
},
{
label: conv({ hans: 'F7: 与维基共享资源文件重复的文件', hant: 'F7: 與維基共享資源檔案重複的檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F7|F7]]: 与[[维基共享资源]]文件重复的文件', hant: '[[Wikipedia:CSD#F7|F7]]: 與[[維基共享資源]]檔案重複的檔案' })
},
{
label: conv({ hans: 'F10: 可被替代的非自由著作权文件', hant: 'F10: 可被替代的非自由版權檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F10|F10]]: 可被替代的非自由著作权文件', hant: '[[Wikipedia:CSD#F10|F10]]: 可被替代的非自由版權檔案' })
},
{
label: conv({ hans: 'O1: 用户请求删除自己的用户页或其子页面', hant: 'O1: 使用者請求刪除自己的使用者頁面或其子頁面' }),
value: conv({ hans: '[[Wikipedia:CSD#O1|O1]]: 用户请求删除自己的[[Help:用户页|用户页]]或其子页面。', hant: '[[Wikipedia:CSD#O1|O1]]: 使用者請求刪除自己的[[Help:用户页|使用者頁面]]或其子頁面。' })
},
{
label: conv({ hans: 'O4: 空的分类(没有条目也没有子分类)', hant: 'O4: 空的分類(沒有條目也沒有子分類)' }),
value: conv({ hans: '[[Wikipedia:CSD#O4|O4]]: 空的分类(没有条目也没有子分类)。', hant: '[[Wikipedia:CSD#O4|O4]]: 空的分類(沒有條目也沒有子分類)。' })
},
{
label: conv({ hans: 'O7: 废弃草稿', hant: 'O7: 廢棄草稿' }),
value: conv({ hans: '[[Wikipedia:CSD#O7|O7]]: 废弃草稿。', hant: '[[Wikipedia:CSD#O7|O7]]: 廢棄草稿。' })
},
{
label: conv({ hans: 'R2: 跨命名空间的重定向', hant: 'R2: 跨命名空間的重新導向' }),
value: conv({ hans: '[[WP:CSD#R2|R2]]: 跨[[H:NS|命名空间]]的[[WP:R|重定向]]', hant: '[[WP:CSD#R2|R2]]: 跨[[H:NS|命名空間]]的[[WP:R|重新導向]]' })
}
];
Twinkle.batchdelete.callback.change_common_reason = function twinklebatchdeleteCallbackChangeCustomReason(e) {
if (e.target.form.reason.value !== '') {
e.target.form.reason.value = Morebits.string.appendPunctuation(e.target.form.reason.value);
}
e.target.form.reason.value += e.target.value;
e.target.value = '';
};
Twinkle.batchdelete.callback.toggleSubpages = function twDbatchToggleSubpages(e) {
var form = e.target.form;
var newPageList;
if (e.target.checked) {
form.delete_subpage_redirects.checked = form.delete_redirects.checked;
form.delete_subpage_talks.checked = form.delete_talk.checked;
form.unlink_subpages.checked = form.unlink_page.checked;
// If lists of subpages were already loaded once, they are
// available without use of any API calls
if (subpagesLoaded) {
$.each(Twinkle.batchdelete.pages, function(i, el) {
// Get back the subgroup from subgroup_, where we saved it
if (el.subgroup === null && el.subgroup_) {
el.subgroup = el.subgroup_;
}
});
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
Morebits.quickForm.getElements(newPageList, 'pages.subpages').forEach(generateArrowLinks);
return;
}
// Proceed with API calls to get list of subpages
var loadingText = '<strong id="dbatch-subpage-loading">' + conv({ hans: '加载中...', hant: '載入中...' }) + '</strong>';
$(e.target).after(loadingText);
var pages = $(form.pages).map(function(i, el) {
return el.value;
}).get();
var subpageLister = new Morebits.batchOperation();
subpageLister.setOption('chunkSize', Twinkle.getPref('batchChunks'));
subpageLister.setPageList(pages);
subpageLister.run(function worker (pageName) {
var pageTitle = mw.Title.newFromText(pageName);
// No need to look for subpages in main/file/mediawiki space
if ([0, 6, 8].indexOf(pageTitle.namespace) > -1) {
subpageLister.workerSuccess();
return;
}
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取 ', hant: '正在取得 ' }) + pageName + conv({ hans: ' 的子页面', hant: ' 的子頁面' }), {
action: 'query',
prop: 'revisions|info|imageinfo',
generator: 'allpages',
rvprop: 'size',
inprop: 'protection',
gapprefix: pageTitle.title + '/',
gapnamespace: pageTitle.namespace,
gaplimit: 'max', // 500 is max for normal users, 5000 for bots and sysops
pageNameFull: pageName // Not used by API, but added for access in onSuccess()
}, function onSuccess(apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page');
var subpageList = [];
$pages.each(function(index, page) {
var $page = $(page);
var ns = $page.attr('ns');
var title = $page.attr('title');
var isRedir = $page.attr('redirect') === '';
var $editprot = $page.find('pr[type="edit"][level="sysop"]');
var isProtected = $editprot.length > 0;
var size = $page.find('rev').attr('size');
var metadata = [];
if (isRedir) {
metadata.push('redirect');
}
if (isProtected) {
metadata.push(conv({ hans: '全保护,', hant: '全保護,' }) +
($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)') + conv({ hans: '过期', hant: '過期' }));
}
if (ns === '6') { // mimic what delimages used to show for files
metadata.push(conv({ hans: '上传者:', hant: '上傳者:' }) + $page.find('ii').attr('user'));
metadata.push(conv({ hans: '最后编辑:', hant: '最後編輯:' }) + $page.find('rev').attr('user'));
} else {
metadata.push(mw.language.convertNumber(size) + conv({ hans: '字节', hant: '位元組' }));
}
subpageList.push({
label: title + (metadata.length ? ' (' + metadata.join('; ') + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
});
});
if (subpageList.length) {
var pageName = apiobj.query.pageNameFull;
Twinkle.batchdelete.pages[pageName].subgroup = {
type: 'checkbox',
name: 'subpages',
className: 'dbatch-subpages',
shiftClickSupport: true,
list: subpageList
};
}
subpageLister.workerSuccess();
}, null /* statusElement */, function onFailure() {
subpageLister.workerFailure();
});
wikipedia_api.post();
}, function postFinish () {
// List 'em on the interface
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
Morebits.quickForm.getElements(newPageList, 'pages.subpages').forEach(generateArrowLinks);
subpagesLoaded = true;
// Remove "Loading... " text
$('#dbatch-subpage-loading').remove();
});
} else if (!e.target.checked) {
$.each(Twinkle.batchdelete.pages, function(i, el) {
if (el.subgroup) {
// Remove subgroup after saving its contents in subgroup_
// so that it can be retrieved easily if user decides to
// delete the subpages again
el.subgroup_ = el.subgroup;
el.subgroup = null;
}
});
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
}
};
Twinkle.batchdelete.callback.evaluate = function twinklebatchdeleteCallbackEvaluate(event) {
Morebits.wiki.actionCompleted.notice = conv({ hans: '批量删除已完成', hant: '批次刪除已完成' });
var form = event.target;
var numProtected = $(Morebits.quickForm.getElements(form, 'pages')).filter(function(index, element) {
return element.checked && element.nextElementSibling.style.color === 'red';
}).length;
if (numProtected > 0 && !confirm(conv({ hans: '您正要删除 ', hant: '您正要刪除 ' }) + mw.language.convertNumber(numProtected) + conv({ hans: ' 个全保护页面,您确定吗?', hant: ' 個全保護頁面,您確定嗎?' }))) {
return;
}
var pages = form.getChecked('pages');
var subpages = form.getChecked('pages.subpages');
var reason = form.reason.value;
var delete_page = form.delete_page.checked;
var delete_talk, delete_redirects, delete_subpages;
var delete_subpage_redirects, delete_subpage_talks, unlink_subpages;
if (delete_page) {
delete_talk = form.delete_talk.checked;
delete_redirects = form.delete_redirects.checked;
delete_subpages = form.delete_subpages.checked;
if (delete_subpages) {
delete_subpage_redirects = form.delete_subpage_redirects.checked;
delete_subpage_talks = form.delete_subpage_talks.checked;
unlink_subpages = form.unlink_subpages.checked;
}
}
var unlink_page = form.unlink_page.checked;
var unlink_file = form.unlink_file.checked;
if (!reason) {
alert(conv({ hans: '您需要给出一个理由', hant: '您需要給出一個理由' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
if (!pages) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '没有要删除的内容,中止', hant: '沒有要刪除的內容,中止' }));
return;
}
var pageDeleter = new Morebits.batchOperation(delete_page ? conv({ hans: '正在删除页面', hant: '正在刪除頁面' }) : conv({ hans: '正在启动要求的任务', hant: '正在啟動要求的任務' }));
pageDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
// we only need the initial status lines if we're deleting the pages in the pages array
pageDeleter.setOption('preserveIndividualStatusLines', delete_page);
pageDeleter.setPageList(pages);
pageDeleter.run(function worker(pageName) {
var params = {
page: pageName,
delete_page: delete_page,
delete_talk: delete_talk,
delete_redirects: delete_redirects,
unlink_page: unlink_page,
unlink_file: unlink_file && new RegExp('^' + Morebits.namespaceRegex(6) + ':', 'i').test(pageName),
reason: reason,
pageDeleter: pageDeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + pageName);
wikipedia_page.setCallbackParameters(params);
if (delete_page) {
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.deletePage(Twinkle.batchdelete.callbacks.doExtras, pageDeleter.workerFailure);
} else {
Twinkle.batchdelete.callbacks.doExtras(wikipedia_page);
}
}, function postFinish() {
if (delete_subpages) {
var subpageDeleter = new Morebits.batchOperation(conv({ hans: '正在删除子页面', hant: '正在刪除子頁面' }));
subpageDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
subpageDeleter.setOption('preserveIndividualStatusLines', true);
subpageDeleter.setPageList(subpages);
subpageDeleter.run(function(pageName) {
var params = {
page: pageName,
delete_page: true,
delete_talk: delete_subpage_talks,
delete_redirects: delete_subpage_redirects,
unlink_page: unlink_subpages,
unlink_file: false,
reason: reason,
pageDeleter: subpageDeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除子页面 ', hant: '正在刪除子頁面 ' }) + pageName);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.deletePage(Twinkle.batchdelete.callbacks.doExtras, pageDeleter.workerFailure);
});
}
});
};
Twinkle.batchdelete.callbacks = {
// this stupid parameter name is a temporary thing until I implement an overhaul
// of Morebits.wiki.* callback parameters
doExtras: function(thingWithParameters) {
var params = thingWithParameters.parent ? thingWithParameters.parent.getCallbackParameters() :
thingWithParameters.getCallbackParameters();
// the initial batch operation's job is to delete the page, and that has
// succeeded by now
params.pageDeleter.workerSuccess(thingWithParameters);
var query, wikipedia_api;
if (params.unlink_page) {
Twinkle.batchdelete.unlinkCache = {};
query = {
action: 'query',
list: 'backlinks',
blfilterredir: 'nonredirects',
blnamespace: [0, 100], // main space and portal space only
bltitle: params.page,
bllimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取链入', hant: '正在取得連入' }), query, Twinkle.batchdelete.callbacks.unlinkBacklinksMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.unlink_file) {
query = {
action: 'query',
list: 'imageusage',
iutitle: params.page,
iulimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取文件链入', hant: '正在取得檔案連入' }), query, Twinkle.batchdelete.callbacks.unlinkImageInstancesMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.delete_page) {
if (params.delete_redirects) {
query = {
action: 'query',
titles: params.page,
prop: 'redirects',
rdlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取重定向', hant: '正在取得重新導向' }), query, Twinkle.batchdelete.callbacks.deleteRedirectsMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.delete_talk) {
var pageTitle = mw.Title.newFromText(params.page);
if (pageTitle && pageTitle.namespace % 2 === 0 && pageTitle.namespace !== 2) {
pageTitle.namespace++; // now pageTitle is the talk page title!
query = {
action: 'query',
titles: pageTitle.toText()
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在检查讨论页面是否存在', hant: '正在檢查討論頁面是否存在' }), query, Twinkle.batchdelete.callbacks.deleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = pageTitle.toText();
wikipedia_api.post();
}
}
}
},
deleteRedirectsMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('rd').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var redirectDeleter = new Morebits.batchOperation(conv({ hans: '正在删除到 ', hant: '正在刪除到 ' }) + apiobj.params.page + conv({ hans: ' 的重定向', hant: ' 的重新導向' }));
redirectDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
redirectDeleter.setPageList(pages);
redirectDeleter.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除 ', hant: '正在刪除 ' }) + pageName);
wikipedia_page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '指向已删页面“', hant: '指向已刪頁面「' }) + apiobj.params.page + conv({ hans: '”的重定向', hant: '」的重新導向' }));
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.deletePage(redirectDeleter.workerSuccess, redirectDeleter.workerFailure);
});
},
deleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
if (!exists) {
// no talk page; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + apiobj.params.page + conv({ hans: ' 的讨论页', hant: ' 的討論頁' }));
page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '已删页面“', hant: '已刪頁面「' }) + apiobj.params.page + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.deletePage();
},
unlinkBacklinksMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('bl').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var unlinker = new Morebits.batchOperation('正在取消到 ' + apiobj.params.page + conv({ hans: ' 的链入', hant: ' 的連入' }));
unlinker.setOption('chunkSize', Twinkle.getPref('batchChunks'));
unlinker.setPageList(pages);
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, '正在取消 ' + pageName + conv({ hans: ' 上的链入', hant: ' 上的連入' }));
var params = $.extend({}, apiobj.params);
params.title = pageName;
params.unlinker = unlinker;
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.batchdelete.callbacks.unlinkBacklinks);
});
},
unlinkBacklinks: function(pageobj) {
var params = pageobj.getCallbackParameters();
if (!pageobj.exists()) {
// we probably just deleted it, as a recursive backlink
params.unlinker.workerSuccess(pageobj);
return;
}
var text;
if (params.title in Twinkle.batchdelete.unlinkCache) {
text = Twinkle.batchdelete.unlinkCache[params.title];
} else {
text = pageobj.getPageText();
}
var old_text = text;
var wikiPage = new Morebits.wikitext.page(text);
text = wikiPage.removeLink(params.page).getText();
Twinkle.batchdelete.unlinkCache[params.title] = text;
if (text === old_text) {
// Nothing to do, return
params.unlinker.workerSuccess(pageobj);
return;
}
pageobj.setEditSummary(conv({ hans: '取消到已删页面', hant: '取消到已刪頁面' }) + params.page + conv({ hans: '的链入', hant: '的連入' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setPageText(text);
pageobj.setCreateOption('nocreate');
pageobj.setMaxConflictRetries(10);
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
},
unlinkImageInstancesMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('iu').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var unlinker = new Morebits.batchOperation('正在取消到 ' + apiobj.params.page + conv({ hans: ' 的链入', hant: ' 的連入' }));
unlinker.setOption('chunkSize', Twinkle.getPref('batchChunks'));
unlinker.setPageList(pages);
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, '取消 ' + pageName + conv({ hans: ' 的文件使用', hant: ' 的檔案使用' }));
var params = $.extend({}, apiobj.params);
params.title = pageName;
params.unlinker = unlinker;
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.batchdelete.callbacks.unlinkImageInstances);
});
},
unlinkImageInstances: function(pageobj) {
var params = pageobj.getCallbackParameters();
if (!pageobj.exists()) {
// we probably just deleted it, as a recursive backlink
params.unlinker.workerSuccess(pageobj);
return;
}
var image = params.page.replace(new RegExp('^' + Morebits.namespaceRegex(6) + ':'), '');
var text;
if (params.title in Twinkle.batchdelete.unlinkCache) {
text = Twinkle.batchdelete.unlinkCache[params.title];
} else {
text = pageobj.getPageText();
}
var old_text = text;
var wikiPage = new Morebits.wikitext.page(text);
text = wikiPage.commentOutImage(image, conv({ hans: '因文件已删,故注解', hant: '因檔案已刪,故註解' })).getText();
Twinkle.batchdelete.unlinkCache[params.title] = text;
if (text === old_text) {
pageobj.getStatusElement().error('在 ' + pageobj.getPageName() + ' 上取消 ' + image + conv({ hans: ' 的文件使用失败', hant: ' 的檔案使用失敗' }));
params.unlinker.workerFailure(pageobj);
return;
}
pageobj.setEditSummary(conv({ hans: '取消使用已被删除文件', hant: '取消使用已被刪除檔案' }) + image + conv({ hans: ',因为:', hant: ',因為:' }) + params.reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setPageText(text);
pageobj.setCreateOption('nocreate');
pageobj.setMaxConflictRetries(10);
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
}
};
Twinkle.addInitCallback(Twinkle.batchdelete, 'batchdelete');
})(jQuery);
// </nowiki>
78e36fdf5872d8b813d05aea841267b47a7b19f7
MediaWiki:Gadget-twinklebatchundelete.js
8
167
336
2023-11-06T13:17:10Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklebatchundelete.js: Batch undelete module
****************************************
* Mode of invocation: Tab ("Und-batch")
* Active on: Existing user and project pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.batchundelete = function twinklebatchundelete() {
if (!Morebits.userIsSysop || !mw.config.get('wgArticleId') || (
mw.config.get('wgNamespaceNumber') !== mw.config.get('wgNamespaceIds').user &&
mw.config.get('wgNamespaceNumber') !== mw.config.get('wgNamespaceIds').project)) {
return;
}
Twinkle.addPortletLink(Twinkle.batchundelete.callback, conv({ hans: '批复', hant: '批復' }), 'tw-batch-undel', conv({ hans: '反删除页面', hant: '反刪除頁面' }));
};
Twinkle.batchundelete.callback = function twinklebatchundeleteCallback() {
var Window = new Morebits.simpleWindow(600, 400);
Window.setScriptName('Twinkle');
Window.setTitle(conv({ hans: '批量反删除', hant: '批次反刪除' }));
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#batchundelete');
var form = new Morebits.quickForm(Twinkle.batchundelete.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如果存在已删除的讨论页,也恢复', hant: '如果存在已刪除的討論頁,也恢復' }),
name: 'undel_talk',
value: 'undel_talk',
checked: true
}
]
});
form.append({
type: 'input',
name: 'reason',
label: '理由:',
size: 60
});
var statusdiv = document.createElement('div');
statusdiv.style.padding = '15px'; // just so it doesn't look broken
Window.setContent(statusdiv);
Morebits.status.init(statusdiv);
Window.display();
var query = {
action: 'query',
generator: 'links',
prop: 'info',
inprop: 'protection',
titles: mw.config.get('wgPageName'),
gpllimit: Twinkle.getPref('batchMax')
};
var statelem = new Morebits.status(conv({ hans: '抓取页面列表', hant: '抓取頁面列表' }));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '加载中…', hant: '載入中…' }), query, function (apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page[missing]');
var list = [];
$pages.each(function(index, page) {
var $page = $(page);
var title = $page.attr('title');
var $editprot = $page.find('pr[type="create"][level="sysop"]');
var isProtected = $editprot.length > 0;
list.push({
label: title + (isProtected ? '(' + conv({ hans: '全保护,', hant: '全保護,' }) + ($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)' + conv({ hans: '过期', hant: '過期' })) + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
});
});
apiobj.params.form.append({ type: 'header', label: conv({ hans: '待恢复页面', hant: '待恢復頁面' }) });
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'pages',
shiftClickSupport: true,
list: list
});
apiobj.params.form.append({ type: 'submit' });
var result = apiobj.params.form.render();
apiobj.params.Window.setContent(result);
}, statelem);
wikipedia_api.params = { form: form, Window: Window };
wikipedia_api.post();
};
Twinkle.batchundelete.callback.evaluate = function(event) {
Morebits.wiki.actionCompleted.notice = conv({ hans: '反删除已完成', hant: '反刪除已完成' });
var numProtected = $(Morebits.quickForm.getElements(event.target, 'pages')).filter(function(index, element) {
return element.checked && element.nextElementSibling.style.color === 'red';
}).length;
if (numProtected > 0 && !confirm(conv({ hans: '您正要反删除 ', hant: '您正要反刪除 ' }) + numProtected + conv({ hans: ' 个全保护页面,您确定吗?', hant: ' 個全保護頁面,您確定嗎?' }))) {
return;
}
var pages = event.target.getChecked('pages');
var reason = event.target.reason.value;
var undel_talk = event.target.reason.value;
if (!reason) {
alert('您需要指定理由。');
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(event.target);
if (!pages) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '没什么要反删除的,取消操作', hant: '沒什麼要反刪除的,取消操作' }));
return;
}
var pageUndeleter = new Morebits.batchOperation(conv({ hans: '反删除页面', hant: '反刪除頁面' }));
pageUndeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
pageUndeleter.setOption('preserveIndividualStatusLines', true);
pageUndeleter.setPageList(pages);
pageUndeleter.run(function(pageName) {
var params = {
page: pageName,
undel_talk: undel_talk,
reason: reason,
pageUndeleter: pageUndeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '反删除页面', hant: '反刪除頁面' }) + pageName);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.setMaxRetries(3); // temporary increase from 2 to make batchundelete more likely to succeed [[phab:T222402]] #613
wikipedia_page.undeletePage(Twinkle.batchundelete.callbacks.doExtras, pageUndeleter.workerFailure);
});
};
Twinkle.batchundelete.callbacks = {
// this stupid parameter name is a temporary thing until I implement an overhaul
// of Morebits.wiki.* callback parameters
doExtras: function(thingWithParameters) {
var params = thingWithParameters.parent ? thingWithParameters.parent.getCallbackParameters() :
thingWithParameters.getCallbackParameters();
// the initial batch operation's job is to delete the page, and that has
// succeeded by now
params.pageUndeleter.workerSuccess(thingWithParameters);
var query, wikipedia_api;
if (params.undel_talk) {
var talkpagename = new mw.Title(params.page).getTalkPage().getPrefixedText();
if (talkpagename !== params.page) {
query = {
action: 'query',
prop: 'deletedrevisions',
drvprop: 'ids',
drvlimit: 1,
titles: talkpagename
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '检查讨论页的已删版本', hant: '檢查討論頁的已刪版本' }), query, Twinkle.batchundelete.callbacks.undeleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = talkpagename;
wikipedia_api.post();
}
}
},
undeleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
var delrevs = $(xml).find('rev').attr('revid');
if (exists || !delrevs) {
// page exists or has no deleted revisions; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在反删除', hant: '正在反刪除' }) + apiobj.params.page + conv({ hans: '的讨论页', hant: '的討論頁' }));
page.setEditSummary(conv({ hans: '反删除“', hant: '反刪除「' }) + apiobj.params.page + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.undeletePage();
}
};
Twinkle.addInitCallback(Twinkle.batchundelete, 'batchundelete');
})(jQuery);
// </nowiki>
a710c6992c48f371b4b4fa581e9692cc2a7ee0d2
MediaWiki:Gadget-twinkleblock.js
8
153
308
2023-11-06T13:17:13Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
var conv = require('ext.gadget.HanAssist').conv;
var api = new mw.Api(), relevantUserName, blockedUserName;
var menuFormattedNamespaces = $.extend({}, mw.config.get('wgFormattedNamespaces'));
menuFormattedNamespaces[0] = conv({ hans: '(条目)', hant: '(條目)' });
var blockActionText = {
block: conv({ hans: '封禁', hant: '封鎖' }),
reblock: conv({ hans: '重新封禁', hant: '重新封鎖' }),
unblock: conv({ hans: '解除封禁', hant: '解除封鎖' })
};
/*
****************************************
*** twinkleblock.js: Block module
****************************************
* Mode of invocation: Tab ("Block")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
*/
Twinkle.block = function twinkleblock() {
relevantUserName = Morebits.wiki.flow.relevantUserName(true);
// should show on Contributions or Block pages, anywhere there's a relevant user
// Ignore ranges wider than the CIDR limit
// zhwiki: Enable for non-admins
if ((Morebits.userIsSysop || !mw.util.isIPAddress(relevantUserName, true)) && relevantUserName && (!Morebits.ip.isRange(relevantUserName) || Morebits.ip.validCIDR(relevantUserName))) {
Twinkle.addPortletLink(Twinkle.block.callback, conv({ hans: '封禁', hant: '封鎖' }), 'tw-block', conv({ hans: '封禁相关用户', hant: '封鎖相關使用者' }));
}
};
Twinkle.block.callback = function twinkleblockCallback() {
if (relevantUserName === mw.config.get('wgUserName') &&
!confirm(conv({ hans: '您即将对自己执行封禁相关操作!确认要继续吗?', hant: '您即將對自己執行封鎖相關操作!確認要繼續嗎?' }))) {
return;
}
Twinkle.block.currentBlockInfo = undefined;
Twinkle.block.field_block_options = {};
Twinkle.block.field_template_options = {};
var Window = new Morebits.simpleWindow(650, 530);
// need to be verbose about who we're blocking
Window.setTitle(conv({ hans: '封禁或向', hant: '封鎖或向' }) + relevantUserName + conv({ hans: '发出封禁模板', hant: '發出封鎖模板' }));
Window.setScriptName('Twinkle');
Window.addFooterLink('封禁模板', 'Wikipedia:模板消息/用戶討論命名空間#封禁');
Window.addFooterLink(conv({ hans: '封禁方针', hant: '封鎖方針' }), 'WP:BLOCK');
Window.addFooterLink(conv({ hans: '封禁设置', hant: '封鎖設定' }), 'WP:TW/PREF#block');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#block');
var form = new Morebits.quickForm(Twinkle.block.callback.evaluate);
var actionfield = form.append({
type: 'field',
label: conv({ hans: '操作类型', hant: '操作類別' })
});
actionfield.append({
type: 'checkbox',
name: 'actiontype',
event: Twinkle.block.callback.change_action,
list: [
{
label: conv({ hans: '封禁用户', hant: '封鎖使用者' }),
value: 'block',
tooltip: conv({ hans: '用选择的选项全站封禁相关用户,如果未勾选部分封禁则为全站封禁。', hant: '用選擇的選項全站封鎖相關使用者,如果未勾選部分封鎖則為全站封鎖。' }),
hidden: !Morebits.userIsSysop,
checked: Morebits.userIsSysop
},
{
label: conv({ hans: '部分封禁', hant: '部分封鎖' }),
value: 'partial',
tooltip: conv({ hans: '启用部分封禁及部分封禁模板。', hant: '啟用部分封鎖及部分封鎖模板。' }),
hidden: !Morebits.userIsSysop,
checked: Twinkle.getPref('defaultToPartialBlocks') // Overridden if already blocked
},
{
label: conv({ hans: '加入封禁模板到用户讨论页', hant: '加入封鎖模板到使用者討論頁' }),
value: 'template',
tooltip: conv({ hans: '如果执行封禁的管理员忘记发出封禁模板,或你封禁了用户而没有给其发出模板,则你可以用此来发出合适的模板。勾选部分封禁以使用部分封禁模板。', hant: '如果執行封鎖的管理員忘記發出封鎖模板,或你封鎖了使用者而沒有給其發出模板,則你可以用此來發出合適的模板。勾選部分封鎖以使用部分封鎖模板。' }),
// Disallow when viewing the block dialog on an IP range
hidden: !Morebits.userIsSysop,
checked: Morebits.userIsSysop && !Morebits.ip.isRange(relevantUserName),
disabled: Morebits.ip.isRange(relevantUserName)
},
{
label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }),
value: 'tag',
tooltip: conv({ hans: '将用户页替换成相关的标记模板,仅限永久封禁使用。', hant: '將使用者頁面替換成相關的標記模板,僅限永久封鎖使用。' }),
hidden: true,
checked: !Morebits.userIsSysop
},
{
label: conv({ hans: '保护用户页', hant: '保護使用者頁面' }),
value: 'protect',
tooltip: conv({ hans: '全保护用户页,仅限永久封禁使用。', hant: '全保護使用者頁面,僅限永久封鎖使用。' }),
hidden: true
},
{
label: conv({ hans: '解除封禁用户', hant: '解除封鎖使用者' }),
value: 'unblock',
tooltip: conv({ hans: '解除封禁相关用户。', hant: '解除封鎖相關使用者。' }),
hidden: !Morebits.userIsSysop
}
]
});
/*
Add option for IPv6 ranges smaller than /64 to upgrade to the 64
CIDR ([[WP:/64]]). This is one of the few places where we want
wgRelevantUserName since this depends entirely on the original user.
In theory, we shouldn't use Morebits.ip.get64 here since since we want
to exclude functionally-equivalent /64s. That'd be:
// if (mw.util.isIPv6Address(Morebits.wiki.flow.relevantUserName(true), true) &&
// (mw.util.isIPv6Address(Morebits.wiki.flow.relevantUserName(true)) || parseInt(Morebits.wiki.flow.relevantUserName(true).replace(/^(.+?)\/?(\d{1,3})?$/, '$2'), 10) > 64)) {
In practice, though, since functionally-equivalent ranges are
(mis)treated as separate by MediaWiki's logging ([[phab:T146628]]),
using Morebits.ip.get64 provides a modicum of relief in thise case.
*/
var sixtyFour = Morebits.ip.get64(Morebits.wiki.flow.relevantUserName(true));
if (sixtyFour && sixtyFour !== Morebits.wiki.flow.relevantUserName(true)) {
var block64field = form.append({
type: 'field',
label: conv({ hans: '转换为/64段封禁', hant: '轉換為/64段封鎖' }),
name: 'field_64'
});
block64field.append({
type: 'div',
style: 'margin-bottom: 0.5em',
label: [$.parseHTML('<a target="_blank" href="' + mw.util.getUrl('en:WP:/64') + '">' + conv({ hans: '直接封禁/64段', hant: '直接封鎖/64段' }) + '</a>')[0], '(',
$.parseHTML('<a target="_blank" href="' + mw.util.getUrl('Special:Contributions/' + sixtyFour) + '">' + sixtyFour + '</a>)')[0], conv({ hans: ')有益无害。', hant: ')有益無害。' })]
});
block64field.append({
type: 'checkbox',
name: 'block64',
event: Twinkle.block.callback.change_block64,
list: [{
checked: Twinkle.getPref('defaultToBlock64'),
label: conv({ hans: '改成封禁/64', hant: '改成封鎖/64' }),
value: 'block64',
tooltip: Morebits.ip.isRange(Morebits.wiki.flow.relevantUserName(true)) ? conv({ hans: '将不会发送模板通知。', hant: '將不會發送模板通知。' }) : conv({ hans: '任何模板将会发送给原始IP:', hant: '任何模板將會發送給原始IP:' }) + Morebits.wiki.flow.relevantUserName(true)
}]
});
}
form.append({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
form.append({ type: 'field', label: conv({ hans: '模板选项', hant: '模板選項' }), name: 'field_template_options' });
form.append({ type: 'field', label: conv({ hans: '封禁选项', hant: '封鎖選項' }), name: 'field_block_options' });
form.append({ type: 'field', label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }), name: 'field_tag_options' });
form.append({ type: 'field', label: conv({ hans: '解除封禁选项', hant: '解除封鎖選項' }), name: 'field_unblock_options' });
form.append({ type: 'submit', label: '提交' });
var result = form.render();
Window.setContent(result);
Window.display();
result.root = result;
Twinkle.block.fetchUserInfo(function() {
if (Twinkle.block.isRegistered) {
var $form = $(result);
Morebits.quickForm.setElementVisibility($form.find('[name=actiontype][value=tag]').parent(), true);
if (Morebits.userIsSysop) {
Morebits.quickForm.setElementVisibility($form.find('[name=actiontype][value=protect]').parent(), true);
}
}
// Toggle initial partial state depending on prior block type,
// will override the defaultToPartialBlocks pref
if (blockedUserName === relevantUserName) {
$(result).find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
}
// clean up preset data (defaults, etc.), done exactly once, must be before Twinkle.block.callback.change_action is called
Twinkle.block.transformBlockPresets();
// init the controls after user and block info have been fetched
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
if (result.block64 && result.block64.checked) {
// Calls the same change_action event once finished
result.block64.dispatchEvent(evt);
} else {
result.actiontype[0].dispatchEvent(evt);
}
});
};
// Store fetched user data, only relevant if switching IPv6 to a /64
Twinkle.block.fetchedData = {};
// Processes the data from a a query response, separated from
// Twinkle.block.fetchUserInfo to allow reprocessing of already-fetched data
Twinkle.block.processUserInfo = function twinkleblockProcessUserInfo(data, fn) {
var blockinfo = data.query.blocks[0],
userinfo = data.query.users[0];
// If an IP is blocked *and* rangeblocked, the above finds
// whichever block is more recent, not necessarily correct.
// Three seems... unlikely
if (data.query.blocks.length > 1 && blockinfo.user !== relevantUserName) {
blockinfo = data.query.blocks[1];
}
// Cache response, used when toggling /64 blocks
Twinkle.block.fetchedData[userinfo.name] = data;
Twinkle.block.isRegistered = !!userinfo.userid;
if (Twinkle.block.isRegistered) {
Twinkle.block.userIsBot = !!userinfo.groupmemberships && userinfo.groupmemberships.map(function(e) {
return e.group;
}).indexOf('bot') !== -1;
} else {
Twinkle.block.userIsBot = false;
}
if (blockinfo) {
// handle frustrating system of inverted boolean values
blockinfo.disabletalk = blockinfo.allowusertalk === undefined;
blockinfo.hardblock = blockinfo.anononly === undefined;
}
// will undefine if no blocks present
Twinkle.block.currentBlockInfo = blockinfo;
blockedUserName = Twinkle.block.currentBlockInfo && Twinkle.block.currentBlockInfo.user;
// Semi-busted on ranges, see [[phab:T270737]] and [[phab:T146628]].
// Basically, logevents doesn't treat functionally-equivalent ranges
// as equivalent, meaning any functionally-equivalent IP range is
// misinterpreted by the log throughout. Without logevents
// redirecting (like Special:Block does) we would need a function to
// parse ranges, which is a pain. IPUtils has the code, but it'd be a
// lot of cruft for one purpose.
Twinkle.block.hasBlockLog = !!data.query.logevents.length;
Twinkle.block.blockLog = Twinkle.block.hasBlockLog && data.query.logevents;
// Used later to check if block status changed while filling out the form
Twinkle.block.blockLogId = Twinkle.block.hasBlockLog ? data.query.logevents[0].logid : false;
if (typeof fn === 'function') {
return fn();
}
};
Twinkle.block.fetchUserInfo = function twinkleblockFetchUserInfo(fn) {
var query = {
format: 'json',
action: 'query',
list: 'blocks|users|logevents',
letype: 'block',
lelimit: 2, // zhwiki: Add more details
letitle: 'User:' + relevantUserName,
bkprop: 'expiry|reason|flags|restrictions|range|user',
ususers: relevantUserName
};
// bkusers doesn't catch single IPs blocked as part of a range block
if (mw.util.isIPAddress(relevantUserName, true)) {
query.bkip = relevantUserName;
} else {
query.bkusers = relevantUserName;
// groupmemberships only relevant for registered users
query.usprop = 'groupmemberships';
}
api.get(query).then(function(data) {
Twinkle.block.processUserInfo(data, fn);
}, function(msg) {
Morebits.status.init($('div[name="currentblock"] span').last()[0]);
Morebits.status.warn(conv({ hans: '抓取用户信息出错', hant: '抓取使用者資訊出錯' }), msg);
});
};
Twinkle.block.callback.saveFieldset = function twinkleblockCallbacksaveFieldset(fieldset) {
Twinkle.block[$(fieldset).prop('name')] = {};
$(fieldset).serializeArray().forEach(function(el) {
// namespaces and pages for partial blocks are overwritten
// here, but we're handling them elsewhere so that's fine
Twinkle.block[$(fieldset).prop('name')][el.name] = el.value;
});
};
Twinkle.block.callback.change_block64 = function twinkleblockCallbackChangeBlock64(e) {
var $form = $(e.target.form), $block64 = $form.find('[name=block64]');
// Show/hide block64 button
// Single IPv6, or IPv6 range smaller than a /64
var priorName = relevantUserName;
if ($block64.is(':checked')) {
relevantUserName = Morebits.ip.get64(Morebits.wiki.flow.relevantUserName(true));
} else {
relevantUserName = Morebits.wiki.flow.relevantUserName(true);
}
// No templates for ranges, but if the original user is a single IP, offer the option
// (done separately in Twinkle.block.callback.issue_template)
var originalIsRange = Morebits.ip.isRange(Morebits.wiki.flow.relevantUserName(true));
$form.find('[name=actiontype][value=template]').prop('disabled', originalIsRange).prop('checked', !originalIsRange);
// Refetch/reprocess user info then regenerate the main content
var regenerateForm = function() {
// Tweak titlebar text. In theory, we could save the dialog
// at initialization and then use `.setTitle` or
// `dialog('option', 'title')`, but in practice that swallows
// the scriptName and requires `.display`ing, which jumps the
// window. It's just a line of text, so this is fine.
var titleBar = document.querySelector('.ui-dialog-title').firstChild.nextSibling;
titleBar.nodeValue = titleBar.nodeValue.replace(priorName, relevantUserName);
// Correct partial state
$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.getPref('defaultToPartialBlocks'));
if (blockedUserName === relevantUserName) {
$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
}
// Set content appropriately
Twinkle.block.callback.change_action(e);
};
if (Twinkle.block.fetchedData[relevantUserName]) {
Twinkle.block.processUserInfo(Twinkle.block.fetchedData[relevantUserName], regenerateForm);
} else {
Twinkle.block.fetchUserInfo(regenerateForm);
}
};
Twinkle.block.callback.change_action = function twinkleblockCallbackChangeAction(e) {
var field_preset, field_template_options, field_block_options, field_tag_options, field_unblock_options, $form = $(e.target.form);
// Make ifs shorter
var $block = $form.find('[name=actiontype][value=block]');
var blockBox = $block.is(':checked');
var $template = $form.find('[name=actiontype][value=template]');
var templateBox = $template.is(':checked');
var $tag = $form.find('[name=actiontype][value=tag]');
var tagBox = $tag.is(':checked');
var $protect = $form.find('[name=actiontype][value=protect]');
var $partial = $form.find('[name=actiontype][value=partial]');
var partialBox = $partial.is(':checked');
var $unblock = $form.find('[name=actiontype][value=unblock]');
var unblockBox = $unblock.is(':checked');
var blockGroup = partialBox ? Twinkle.block.blockGroupsPartial : Twinkle.block.blockGroups;
if (e.target.value === 'unblock') {
if (!Twinkle.block.currentBlockInfo) {
$unblock.prop('checked', false);
return alert(conv({ hans: '用户没有被封禁', hant: '使用者沒有被封鎖' }));
}
$block.prop('checked', false);
blockBox = false;
$template.prop('checked', false);
templateBox = false;
$tag.prop('checked', false);
$protect.prop('checked', false);
$partial.prop('checked', false);
} else {
$unblock.prop('checked', false);
}
$partial.prop('disabled', !blockBox && !templateBox);
// Add current block parameters as default preset
var prior = { label: conv({ hans: '当前封禁', hant: '目前封鎖' }) };
if (blockedUserName === relevantUserName) {
Twinkle.block.blockPresetsInfo.prior = Twinkle.block.currentBlockInfo;
// value not a valid template selection, chosen below by setting templateName
prior.list = [{ label: conv({ hans: '当前封禁设置', hant: '目前封鎖設定' }), value: 'prior', selected: true }];
// Arrays of objects are annoying to check
if (!blockGroup.some(function(bg) {
return bg.label === prior.label;
})) {
blockGroup.push(prior);
}
// Always ensure proper template exists/is selected when switching modes
if (partialBox) {
Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-pblockindef' : 'uw-pblock';
} else {
if (!Twinkle.block.isRegistered) {
Twinkle.block.blockPresetsInfo.prior.templateName = 'uw-ablock';
} else {
Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-blockindef' : 'uw-block';
}
}
} else {
// But first remove any prior prior
blockGroup = blockGroup.filter(function(bg) {
return bg.label !== prior.label;
});
}
Twinkle.block.callback.saveFieldset($('[name=field_block_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_template_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_tag_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_unblock_options]'));
if (blockBox) {
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'preset',
label: conv({ hans: '选择默认:', hant: '選擇預設:' }),
event: Twinkle.block.callback.change_preset,
list: Twinkle.block.callback.filtered_block_groups(blockGroup)
});
field_block_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '封禁选项', hant: '封鎖選項' }), name: 'field_block_options' });
field_block_options.append({ type: 'div', name: 'currentblock', label: ' ' });
field_block_options.append({ type: 'div', name: 'hasblocklog', label: ' ' });
field_block_options.append({
type: 'select',
name: 'expiry_preset',
label: conv({ hans: '过期时间:', hant: '過期時間:' }),
event: Twinkle.block.callback.change_expiry,
list: [
{ label: conv({ hans: '自定义', hant: '自訂' }), value: 'custom', selected: true },
{ label: conv({ hans: '无限期', hant: '無限期' }), value: 'infinity' },
{ label: conv({ hans: '3小时', hant: '3小時' }), value: '3 hours' },
{ label: conv({ hans: '12小时', hant: '12小時' }), value: '12 hours' },
{ label: '1天', value: '1 day' },
{ label: conv({ hans: '31小时', hant: '31小時' }), value: '31 hours' },
{ label: '2天', value: '2 days' },
{ label: '3天', value: '3 days' },
{ label: conv({ hans: '1周', hant: '1週' }), value: '1 week' },
{ label: conv({ hans: '2周', hant: '2週' }), value: '2 weeks' },
{ label: conv({ hans: '1个月', hant: '1個月' }), value: '1 month' },
{ label: conv({ hans: '3个月', hant: '3個月' }), value: '3 months' },
{ label: conv({ hans: '6个月', hant: '6個月' }), value: '6 months' },
{ label: '1年', value: '1 year' },
{ label: '2年', value: '2 years' },
{ label: '3年', value: '3 years' }
]
});
field_block_options.append({
type: 'input',
name: 'expiry',
label: conv({ hans: '自定义过期时间', hant: '自訂過期時間' }),
tooltip: conv({ hans: '您可以使用相对时间,如“1 minute”或“19 days”;或绝对时间,“yyyymmddhhmm”(如“200602011405”是2006年2月1日14:05 UTC。)', hant: '您可以使用相對時間,如「1 minute」或「19 days」;或絕對時間,「yyyymmddhhmm」(如「200602011405」是2006年2月1日14:05 UTC。)' }),
value: Twinkle.block.field_block_options.expiry || Twinkle.block.field_template_options.template_expiry
});
if (partialBox) { // Partial block
field_block_options.append({
type: 'select',
multiple: true,
name: 'pagerestrictions',
label: conv({ hans: '页面封禁', hant: '頁面封鎖' }),
value: '',
tooltip: conv({ hans: '最多10个页面。', hant: '最多10個頁面。' })
});
var ns = field_block_options.append({
type: 'select',
multiple: true,
name: 'namespacerestrictions',
label: conv({ hans: '命名空间封禁', hant: '命名空間封鎖' }),
value: '',
tooltip: conv({ hans: '指定封禁的命名空间。', hant: '指定封鎖的命名空間。' })
});
$.each(menuFormattedNamespaces, function(number, name) {
// Ignore -1: Special; -2: Media; and 2300-2303: Gadget (talk) and Gadget definition (talk)
if (number >= 0 && number < 830) {
ns.append({ type: 'option', label: name, value: number });
}
});
}
var blockoptions = [
{
checked: Twinkle.block.field_block_options.nocreate,
label: conv({ hans: '禁止创建账户', hant: '禁止建立帳號' }),
name: 'nocreate',
value: '1'
},
{
checked: Twinkle.block.field_block_options.noemail,
label: conv({ hans: '电子邮件停用', hant: '電子郵件停用' }),
name: 'noemail',
value: '1'
},
{
checked: Twinkle.block.field_block_options.disabletalk,
label: conv({ hans: '不能编辑自己的讨论页', hant: '不能編輯自己的討論頁' }),
name: 'disabletalk',
value: '1',
tooltip: partialBox ? conv({ hans: '如果使用部分封禁,不应选择此项,除非您也想要禁止编辑用户讨论页。', hant: '如果使用部分封鎖,不應選擇此項,除非您也想要禁止編輯使用者討論頁。' }) : ''
}
];
if (Twinkle.block.isRegistered) {
blockoptions.push({
checked: Twinkle.block.field_block_options.autoblock,
label: conv({ hans: '自动封禁', hant: '自動封鎖' }),
name: 'autoblock',
value: '1'
});
} else {
blockoptions.push({
checked: Twinkle.block.field_block_options.hardblock,
label: conv({ hans: '阻止登录用户使用该IP地址编辑', hant: '阻止登入使用者使用該IP位址編輯' }),
name: 'hardblock',
value: '1'
});
}
blockoptions.push({
checked: Twinkle.block.field_block_options.watchuser,
label: conv({ hans: '监视该用户的用户页和讨论页', hant: '監視該使用者的使用者頁面和討論頁' }),
name: 'watchuser',
value: '1'
});
blockoptions.push({
checked: true,
label: conv({ hans: '标记当前的破坏中的请求', hant: '標記當前的破壞中的請求' }),
name: 'closevip',
value: '1'
});
field_block_options.append({
type: 'checkbox',
name: 'blockoptions',
list: blockoptions
});
field_block_options.append({
type: 'textarea',
label: conv({ hans: '理由(用于封禁日志):', hant: '理由(用於封鎖日誌):' }),
name: 'reason',
tooltip: conv({ hans: '请考虑在默认的消息中加入有用的详细信息。', hant: '請考慮在預設的訊息中加入有用的詳細資訊。' }),
value: Twinkle.block.field_block_options.reason
});
field_block_options.append({
type: 'div',
name: 'filerlog_label',
label: conv({ hans: '参见:', hant: '參見:' }),
style: 'display:inline-block;font-style:normal !important',
tooltip: conv({ hans: '在封禁理由中标清特殊情况以供其他管理员参考', hant: '在封鎖理由中標清特殊情況以供其他管理員參考' })
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '过滤器日志', hant: '過濾器日誌' }),
checked: false,
value: conv({ hans: '过滤器日志', hant: '過濾器日誌' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'deleted_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '已删除的编辑', hant: '已刪除的編輯' }),
checked: false,
value: conv({ hans: '已删除的编辑', hant: '已刪除的編輯' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '用户讨论页', hant: '使用者討論頁' }),
checked: false,
value: conv({ hans: '用户讨论页', hant: '使用者討論頁' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '过去的封禁记录', hant: '過去的封鎖記錄' }),
checked: false,
value: conv({ hans: '过去的封禁记录', hant: '過去的封鎖記錄' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '跨维基贡献', hant: '跨維基貢獻' }),
checked: false,
value: conv({ hans: '跨维基贡献', hant: '跨維基貢獻' })
}
]
});
// Yet-another-logevents-doesn't-handle-ranges-well
if (blockedUserName === relevantUserName) {
field_block_options.append({ type: 'hidden', name: 'reblock', value: '1' });
}
}
if (templateBox) {
field_template_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '模板选项', hant: '模板選項' }), name: 'field_template_options' });
field_template_options.append({
type: 'select',
name: 'template',
label: conv({ hans: '选择讨论页模板:', hant: '選擇討論頁模板:' }),
event: Twinkle.block.callback.change_template,
list: Twinkle.block.callback.filtered_block_groups(blockGroup, true),
value: Twinkle.block.field_template_options.template
});
field_template_options.append({
type: 'input',
name: 'article',
label: conv({ hans: '链接页面', hant: '連結頁面' }),
value: '',
tooltip: conv({ hans: '可以随通知链接页面,例如破坏的目标。没有条目需要链接则请留空。', hant: '可以隨通知連結頁面,例如破壞的目標。沒有條目需要連結則請留空。' })
});
// Only visible if partial and not blocking
field_template_options.append({
type: 'input',
name: 'area',
label: conv({ hans: '封禁范围', hant: '封鎖範圍' }),
value: '',
tooltip: conv({ hans: '阻止用户编辑的页面或命名空间的可选说明。', hant: '阻止使用者編輯的頁面或命名空間的可選說明。' })
});
if (!blockBox) {
field_template_options.append({
type: 'input',
name: 'template_expiry',
label: '封禁期限:',
value: '',
tooltip: conv({ hans: '封禁时长,如24小时、2周、无限期等。', hant: '封鎖時長,如24小時、2週、無限期等。' })
});
}
field_template_options.append({
type: 'input',
name: 'block_reason',
label: conv({ hans: '“由于…您已被封禁”', hant: '「由於…您已被封鎖」' }),
tooltip: conv({ hans: '可选的理由,用于替换默认理由。只在常规封禁模板中有效。', hant: '可選的理由,用於替換預設理由。只在常規封鎖模板中有效。' }),
value: Twinkle.block.field_template_options.block_reason,
size: 60
});
if (blockBox) {
field_template_options.append({
type: 'checkbox',
name: 'blank_duration',
list: [
{
label: conv({ hans: '不在模板中包含封禁期限', hant: '不在模板中包含封鎖期限' }),
checked: Twinkle.block.field_template_options.blank_duration,
tooltip: conv({ hans: '模板将会显示“一段时间”而不是具体时长', hant: '模板將會顯示「一段時間」而不是具體時長' })
}
]
});
} else {
field_template_options.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '不能编辑自己的讨论页', hant: '不能編輯自己的討論頁' }),
name: 'notalk',
checked: Twinkle.block.field_template_options.notalk,
tooltip: conv({ hans: '用此在封禁模板中指明该用户编辑讨论页的权限已被移除', hant: '用此在封鎖模板中指明該使用者編輯討論頁的權限已被移除' })
},
{
label: conv({ hans: '不能发送电子邮件', hant: '不能傳送電子郵件' }),
name: 'noemail_template',
checked: Twinkle.block.field_template_options.noemail_template,
tooltip: conv({ hans: '用此在封禁模板中指明该用户发送电子邮件的权限已被移除', hant: '用此在封鎖模板中指明該使用者傳送電子郵件的權限已被移除' })
},
{
label: conv({ hans: '不能创建账户', hant: '不能建立帳號' }),
name: 'nocreate_template',
checked: Twinkle.block.field_template_options.nocreate_template,
tooltip: conv({ hans: '用此在封禁模板中指明该用户创建账户的权限已被移除', hant: '用此在封鎖模板中指明該使用者建立帳號的權限已被移除' })
}
]
});
}
var $previewlink = $('<a id="twinkleblock-preview-link">' + conv({ hans: '预览', hant: '預覽' }) + '</a>');
$previewlink.off('click').on('click', function() {
Twinkle.block.callback.preview($form[0]);
});
$previewlink.css({cursor: 'pointer'});
field_template_options.append({ type: 'div', id: 'blockpreview', label: [ $previewlink[0] ] });
field_template_options.append({ type: 'div', id: 'twinkleblock-previewbox', style: 'display: none' });
}
if (tagBox) {
field_tag_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }), name: 'field_tag_options' });
field_tag_options.append({
type: 'checkbox',
name: 'tag',
label: conv({ hans: '选择用户页模板:', hant: '選擇使用者頁面模板:' }),
list: [
{
label: '{{Blocked user}}:' + conv({ hans: '一般永久封禁', hant: '一般永久封鎖' }),
value: 'Blocked user'
},
{
label: '{{Sockpuppet}}:' + conv({ hans: '傀儡账户', hant: '傀儡帳號' }),
value: 'Sockpuppet',
subgroup: [
{
name: 'sppUsername',
type: 'input',
label: conv({ hans: '主账户用户名:', hant: '主帳號使用者名稱:' })
},
{
name: 'sppType',
type: 'select',
label: conv({ hans: '状态:', hant: '狀態:' }),
list: [
{ type: 'option', value: 'blocked', label: 'blocked - ' + conv({ hans: '仅依行为证据认定', hant: '僅依行為證據認定' }), selected: true },
{ type: 'option', value: 'proven', label: 'proven - ' + conv({ hans: '经傀儡调查确认', hant: '經傀儡調查確認' }) },
{ type: 'option', value: 'confirmed', label: 'confirmed - ' + conv({ hans: '经查核确认', hant: '經查核確認' }) }
]
},
{
name: 'sppEvidence',
type: 'input',
label: conv({ hans: '根据……确定:', hant: '根據……確定:' }),
tooltip: conv({ hans: '纯文字或是带[[]]的链接,例如:[[Special:固定链接/xxxxxxxx|用户查核]]', hant: '純文字或是帶[[]]的連結,例如:[[Special:固定链接/xxxxxxxx|用戶查核]]' })
}
]
},
{
label: '{{Sockpuppeteer|blocked}}:' + conv({ hans: '傀儡主账户', hant: '傀儡主帳號' }),
value: 'Sockpuppeteer',
subgroup: [
{
type: 'checkbox',
list: [
{
name: 'spmChecked',
value: 'spmChecked',
label: conv({ hans: '经用户查核确认', hant: '經使用者查核確認' })
}
]
},
{
name: 'spmEvidence',
type: 'input',
label: conv({ hans: '额外理由:', hant: '額外理由:' })
}
]
},
{
label: '{{Locked global account}}:' + conv({ hans: '全域锁定', hant: '全域鎖定' }),
value: 'Locked global account',
subgroup: [
{
type: 'checkbox',
list: [
{
name: 'lockBlocked',
value: 'lockBlocked',
label: conv({ hans: '亦被本地封禁', hant: '亦被本地封鎖' })
}
]
}
]
}
]
});
field_tag_options.append({
type: 'input',
name: 'category',
label: 'Category:……的維基用戶分身' + conv({ hans: '(主账户用户名)', hant: '(主帳號使用者名稱)' }), // no variant conversion for category name
tooltip: conv({ hans: '您通常应该使用{{Sockpuppet}}的主账户参数来产生分类,只有单独使用{{Locked global account}}才需填写此项。', hant: '您通常應該使用{{Sockpuppet}}的主帳號參數來產生分類,只有單獨使用{{Locked global account}}才需填寫此項。' })
});
}
if (unblockBox) {
field_unblock_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '解除封禁选项', hant: '解除封鎖選項' }), name: 'field_unblock_options' });
field_unblock_options.append({
type: 'textarea',
label: conv({ hans: '理由(用于封禁日志):', hant: '理由(用於封鎖日誌):' }),
name: 'reason',
value: Twinkle.block.field_unblock_options.reason
});
}
var oldfield;
if (field_preset) {
oldfield = $form.find('fieldset[name="field_preset"]')[0];
oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
} else {
$form.find('fieldset[name="field_preset"]').hide();
}
if (field_block_options) {
oldfield = $form.find('fieldset[name="field_block_options"]')[0];
oldfield.parentNode.replaceChild(field_block_options.render(), oldfield);
$form.find('fieldset[name="field_64"]').show();
$form.find('[name=pagerestrictions]').select2({
width: '100%',
placeholder: conv({ hans: '输入要阻止用户编辑的页面', hant: '輸入要阻止使用者編輯的頁面' }),
language: {
errorLoading: function() {
return conv({ hans: '搜索词汇不完整或无效', hant: '搜尋詞彙不完整或無效' });
}
},
maximumSelectionLength: 10, // Software limitation [[phab:T202776]]
minimumInputLength: 1, // prevent ajax call when empty
ajax: {
url: mw.util.wikiScript('api'),
dataType: 'json',
delay: 100,
data: function(params) {
var title = mw.Title.newFromText(params.term);
if (!title) {
return;
}
return {
action: 'query',
format: 'json',
list: 'allpages',
apfrom: title.title,
apnamespace: title.namespace,
aplimit: '10'
};
},
processResults: function(data) {
return {
results: data.query.allpages.map(function(page) {
var title = mw.Title.newFromText(page.title, page.ns).toText();
return {
id: title,
text: title
};
})
};
}
},
templateSelection: function(choice) {
return $('<a>').text(choice.text).attr({
href: mw.util.getUrl(choice.text),
target: '_blank'
});
}
});
$form.find('[name=namespacerestrictions]').select2({
width: '100%',
matcher: Morebits.select2.matchers.wordBeginning,
language: {
searching: Morebits.select2.queryInterceptor
},
templateResult: Morebits.select2.highlightSearchMatches,
placeholder: conv({ hans: '选择要禁止用户编辑的命名空间', hant: '選擇要禁止使用者編輯的命名空間' })
});
mw.util.addCSS(
// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
// Adjust font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }' +
// Remove black border
'.select2-container--default.select2-container--focus .select2-selection--multiple { border: 1px solid #aaa; }' +
// Make the tiny cross larger
'.select2-selection__choice__remove { font-size: 130%; }'
);
} else {
$form.find('fieldset[name="field_block_options"]').hide();
$form.find('fieldset[name="field_64"]').hide();
// Clear select2 options
$form.find('[name=pagerestrictions]').val(null).trigger('change');
$form.find('[name=namespacerestrictions]').val(null).trigger('change');
}
if (field_template_options) {
oldfield = $form.find('fieldset[name="field_template_options"]')[0];
oldfield.parentNode.replaceChild(field_template_options.render(), oldfield);
e.target.form.root.previewer = new Morebits.wiki.preview($(e.target.form.root).find('#twinkleblock-previewbox').last()[0]);
} else {
$form.find('fieldset[name="field_template_options"]').hide();
}
if (field_tag_options) {
oldfield = $form.find('fieldset[name="field_tag_options"]')[0];
oldfield.parentNode.replaceChild(field_tag_options.render(), oldfield);
} else {
$form.find('fieldset[name="field_tag_options"]').hide();
}
if (field_unblock_options) {
oldfield = $form.find('fieldset[name="field_unblock_options"]')[0];
oldfield.parentNode.replaceChild(field_unblock_options.render(), oldfield);
} else {
$form.find('fieldset[name="field_unblock_options"]').hide();
}
// Any block, including ranges
if (Twinkle.block.currentBlockInfo) {
// false for an ip covered by a range or a smaller range within a larger range;
// true for a user, single ip block, or the exact range for a range block
var sameUser = blockedUserName === relevantUserName;
Morebits.status.init($('div[name="currentblock"] span').last()[0]);
var statusStr = relevantUserName + '已被' + (Twinkle.block.currentBlockInfo.partial === '' ? conv({ hans: '部分封禁', hant: '部分封鎖' }) : conv({ hans: '全站封禁', hant: '全站封鎖' }));
// Range blocked
if (Twinkle.block.currentBlockInfo.rangestart !== Twinkle.block.currentBlockInfo.rangeend) {
if (sameUser) {
statusStr += conv({ hans: '(段封禁)', hant: '(段封鎖)' });
} else {
// zhwiki: Change order
// Link to the full range
var $rangeblockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: blockedUserName, type: 'block'}) + '">' + (Morebits.ip.get64(relevantUserName) === blockedUserName ? '/64' : blockedUserName) + '</a>)'));
statusStr += conv({ hans: '(位于', hant: '(位於' }) + $rangeblockloglink.html() + conv({ hans: '段封禁内)', hant: '段封鎖內)' });
}
}
if (Twinkle.block.currentBlockInfo.expiry === 'infinity') {
statusStr += conv({ hans: '(无限期)', hant: '(無限期)' });
} else if (new Morebits.date(Twinkle.block.currentBlockInfo.expiry).isValid()) {
statusStr += conv({ hans: '(终止于', hant: '(終止於' }) + new Morebits.date(Twinkle.block.currentBlockInfo.expiry).calendar('utc') + ')';
}
var infoStr = conv({ hans: '此表单将', hant: '此表單將' });
if (sameUser) {
infoStr += conv({ hans: '变更封禁', hant: '變更封鎖' });
if (Twinkle.block.currentBlockInfo.partial === undefined && partialBox) {
infoStr += conv({ hans: '为部分封禁', hant: '為部分封鎖' });
} else if (Twinkle.block.currentBlockInfo.partial === '' && !partialBox) {
infoStr += conv({ hans: '为全站封禁', hant: '為全站封鎖' });
}
infoStr += '。';
} else {
infoStr += conv({ hans: '加上额外的', hant: '加上額外的' }) + (partialBox ? '部分' : '') + conv({ hans: '封禁。', hant: '封鎖。' });
}
Morebits.status.warn(statusStr, infoStr);
// Default to the current block conditions on intial form generation
Twinkle.block.callback.update_form(e, Twinkle.block.currentBlockInfo);
}
// This is where T146628 really comes into play: a rangeblock will
// only return the correct block log if wgRelevantUserName is the
// exact range, not merely a funtional equivalent
if (Twinkle.block.hasBlockLog) {
// zhwiki: Add more details
var blockloginfo = [];
var $blockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', { action: 'view', page: relevantUserName, type: 'block' }) + '">' + conv({ hans: '封禁日志', hant: '封鎖日誌' }) + '</a>)'));
if (Twinkle.block.currentBlockInfo) {
blockloginfo.push(conv({ hans: '封禁详情', hant: '封鎖詳情' }));
} else {
var lastBlockAction = Twinkle.block.blockLog[0],
blockAction = lastBlockAction.action === 'unblock' ? Twinkle.block.blockLog[1] : lastBlockAction;
blockloginfo.push('此' + (Morebits.ip.isRange(relevantUserName) ? conv({ hans: 'IP范围', hant: 'IP範圍' }) : conv({ hans: '用户', hant: '使用者' })) + '曾在');
blockloginfo.push($('<b>' + new Morebits.date(blockAction.timestamp).calendar('utc') + '</b>')[0]);
blockloginfo.push('被' + blockAction.user + conv({ hans: '封禁', hant: '封鎖' }));
blockloginfo.push($('<b>' + Morebits.string.formatTime(blockAction.params.duration) + '</b>')[0]);
if (lastBlockAction.action === 'unblock') {
blockloginfo.push(',' + new Morebits.date(lastBlockAction.timestamp).calendar('utc') + '解封');
} else { // block or reblock
blockloginfo.push(',' + new Morebits.date(blockAction.params.expiry).calendar('utc') + conv({ hans: '过期', hant: '過期' }));
}
}
Morebits.status.init($('div[name="hasblocklog"] span').last()[0]);
Morebits.status.warn(blockloginfo, $blockloglink[0]);
}
// Make sure all the fields are correct based on initial defaults
if (blockBox) {
Twinkle.block.callback.change_preset(e);
} else if (templateBox) {
Twinkle.block.callback.change_template(e);
}
};
/*
* Keep alphabetized by key name, Twinkle.block.blockGroups establishes
* the order they will appear in the interface
*
* Block preset format, all keys accept only 'true' (omit for false) except where noted:
* <title of block template> : {
* autoblock: <autoblock any IP addresses used (for registered users only)>
* disabletalk: <disable user from editing their own talk page while blocked>
* expiry: <string - expiry timestamp, can include relative times like "5 months", "2 weeks" etc>
* forAnonOnly: <show block option in the interface only if the relevant user is an IP>
* forRegisteredOnly: <show block option in the interface only if the relevant user is registered>
* label: <string - label for the option of the dropdown in the interface (keep brief)>
* noemail: prevent the user from sending email through Special:Emailuser
* pageParam: <set if the associated block template accepts a page parameter>
* prependReason: <string - prepends the value of 'reason' to the end of the existing reason, namely for when revoking talk page access>
* nocreate: <block account creation from the user's IP (for anonymous users only)>
* nonstandard: <template does not conform to stewardship of WikiProject User Warnings and may not accept standard parameters>
* reason: <string - block rationale, as would appear in the block log,
* and the edit summary for when adding block template, unless 'summary' is set>
* reasonParam: <set if the associated block template accepts a reason parameter>
* sig: <string - set to ~~~~ if block template does not accept "true" as the value, or set null to omit sig param altogether>
* summary: <string - edit summary for when adding block template to user's talk page, if not set, 'reason' is used>
* suppressArticleInSummary: <set to suppress showing the article name in the edit summary, as with attack pages>
* templateName: <string - name of template to use (instead of key name), entry will be omitted from the Templates list.
* (e.g. use another template but with different block options)>
* useInitialOptions: <when preset is chosen, only change given block options, leave others as they were>
*
* WARNING: 'anononly' and 'allowusertalk' are enabled by default.
* To disable, set 'hardblock' and 'disabletalk', respectively
*/
Twinkle.block.blockPresetsInfo = {
'anonblock': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{anonblock}}',
sig: '~~~~'
},
'blocked proxy': {
expiry: '2 years',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
hardblock: true,
reason: '{{blocked proxy}}',
sig: null
},
'CheckUser block': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{CheckUser block}}',
sig: '~~~~'
},
'checkuserblock-account': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{checkuserblock-account}}',
sig: '~~~~'
},
'school block': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{school block}}',
sig: '~~~~'
},
'range block': {
expiry: '1 week',
reason: '<!-- 請登入您的帳號,若無帳號,請閱讀 https://w.wiki/Jyi -->{{range block}}',
nocreate: true,
nonstandard: true,
forAnonOnly: true,
sig: '~~~~'
},
// uw-prefixed
'uw-3block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '违反[[WP:3RR|回退不过三原则]]', hant: '違反[[WP:3RR|回退不過三原則]]' }),
summary: conv({ hans: '封禁通知:违反[[WP:3RR|回退不过三原则]]', hant: '封鎖通知:違反[[WP:3RR|回退不過三原則]]' })
},
'uw-ablock': {
autoblock: true,
expiry: '1 day',
forAnonOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-adblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:SOAP|散发广告/宣传]]', hant: '[[WP:SOAP|散發廣告/宣傳]]' }),
summary: conv({ hans: '封禁通知:散发[[WP:SOAP|散发广告/宣传]]', hant: '封鎖通知:散發[[WP:SOAP|散發廣告/宣傳]]' }),
templateName: 'uw-block'
},
'uw-block': {
autoblock: true,
expiry: '1 day',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-blockindef': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-blocknotalk': {
disabletalk: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知:禁止编辑讨论页', hant: '封鎖通知:禁止編輯討論頁' }),
suppressArticleInSummary: true
},
'uw-copyrightblock': {
autoblock: true,
expiry: 'infinity',
nocreate: true,
pageParam: true,
reason: conv({ hans: '多次加入[[WP:COPYVIO|侵犯著作权]]的内容', hant: '多次加入[[WP:COPYVIO|侵犯著作權]]的內容' }),
summary: conv({ hans: '封禁通知:持续[[WP:COPYVIO|侵犯著作权]]', hant: '封鎖通知:持續[[WP:COPYVIO|侵犯著作權]]' }),
templateName: 'uw-blockindef'
},
'uw-dblock': {
autoblock: true,
nocreate: true,
reason: conv({ hans: '持续无故删除内容', hant: '持續無故刪除內容' }),
pageParam: true,
summary: conv({ hans: '封禁通知:持续[[WP:VAN|删除内容]]', hant: '封鎖通知:持續[[WP:VAN|刪除內容]]' })
},
'uw-hblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:骚扰|骚扰用户]]', hant: '[[WP:騷擾|騷擾使用者]]' }),
summary: conv({ hans: '封禁通知:[[WP:骚扰|骚扰]]其他用户', hant: '封鎖通知:[[WP:騷擾|騷擾]]其他使用者' }),
templateName: 'uw-block'
},
'uw-npblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VAN|在条目中增加无意义文字]]', hant: '[[WP:VAN|在條目中增加無意義文字]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN|在条目中增加无意义文字]]', hant: '封鎖通知:[[WP:VAN|在條目中增加無意義文字]]' }),
templateName: 'uw-block'
},
'uw-pablock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reason: conv({ hans: '无礼的行为、[[WP:NPA|攻击别人]]', hant: '無禮的行為、[[WP:NPA|攻擊別人]]' }),
summary: conv({ hans: '封禁通知:无礼的行为、[[WP:NPA|人身攻击]]', hant: '封鎖通知:無禮的行為、[[WP:NPA|人身攻擊]]' }),
templateName: 'uw-block'
},
'uw-sblock': {
autoblock: true,
nocreate: true,
reason: conv({ hans: '不断加入[[Wikipedia:垃圾内容|垃圾链接]]', hant: '不斷加入[[Wikipedia:垃圾內容|垃圾連結]]' }),
summary: conv({ hans: '封禁通知:利用维基百科散发[[Wikipedia:垃圾内容|垃圾链接]]', hant: '封鎖通知:利用維基百科散發[[Wikipedia:垃圾內容|垃圾連結]]' })
},
'uw-soablock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:SOAP|散发广告/宣传]]', hant: '[[WP:SOAP|散發廣告/宣傳]]' }),
summary: conv({ hans: '封禁通知:仅[[WP:SOAP|散发广告/宣传]]', hant: '封鎖通知:僅[[WP:SOAP|散發廣告/宣傳]]' }),
templateName: 'uw-block'
},
'uw-sockblock': {
autoblock: true,
expiry: '1 week',
forRegisteredOnly: true,
nocreate: true,
reason: conv({ hans: '滥用[[WP:SOCK|多个账户]]', hant: '濫用[[WP:SOCK|多個帳號]]' }),
summary: conv({ hans: '封禁通知:滥用[[WP:SOCK|多个账户]]', hant: '封鎖通知:濫用[[WP:SOCK|多個帳號]]' }),
templateName: 'uw-block'
},
'uw-softerblock': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-softerblock}}<!-- ' + conv({ hans: '宣传性用户名、软封禁', hant: '宣傳性使用者名稱、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]暗示您的账户代表一个团体、组织或网站', hant: '封鎖通知:您的[[WP:U|使用者名稱]]暗示您的帳號代表一個團體、組織或網站' })
},
'uw-spamublock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reason: '{{uw-spamublock}}<!-- ' + conv({ hans: '宣传性用户名、宣传性编辑', hant: '宣傳性使用者名稱、宣傳性編輯' }) + ' -->',
summary: conv({ hans: '封禁通知:仅[[WP:SOAP|广告宣传]],同时您的用户名违反[[WP:U|用户名方针]]', hant: '封鎖通知:僅[[WP:SOAP|廣告宣傳]],同時您的使用者名稱違反[[WP:U|使用者名稱方針]]' })
},
'uw-ublock': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock}}<!-- ' + conv({ hans: '不当用户名、软封禁', hant: '不當使用者名稱、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的用户名违反[[WP:U|用户名方针]]', hant: '封鎖通知:您的使用者名稱違反[[WP:U|使用者名稱方針]]' })
},
'uw-ublock-double': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock-double}}<!-- ' + conv({ hans: '用户名与其他用户相似、软封禁', hant: '使用者名稱與其他使用者相似、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]与其他维基百科用户过于相似', hant: '封鎖通知:您的[[WP:U|使用者名稱]]與其他維基百科使用者過於相似' })
},
'uw-ucblock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '屡次增加没有[[WP:RS|可靠来源]]的资料', hant: '屢次增加沒有[[WP:RS|可靠來源]]的資料' }),
summary: conv({ hans: '封禁通知:屡次增加没有[[WP:RS|可靠来源]]的资料', hant: '封鎖通知:屢次增加沒有[[WP:RS|可靠來源]]的資料' }),
templateName: 'uw-block'
},
'uw-ublock-wellknown': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock-wellknown}}<!-- ' + conv({ hans: '用户名与知名人物相似、软封禁', hant: '使用者名稱與知名人物相似、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]与知名人物过于相似', hant: '封鎖通知:您的[[WP:U|使用者名稱]]與知名人物過於相似' })
},
'uw-uhblock-double': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reason: '{{uw-uhblock-double}}<!-- ' + conv({ hans: '用户名试图冒充其他用户、硬封禁', hant: '使用者名稱試圖冒充其他使用者、硬封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]试图冒充其他维基百科用户', hant: '封鎖通知:您的[[WP:U|使用者名稱]]試圖冒充其他維基百科使用者' })
},
'uw-ublock|误导': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|误导}}', hant: '{{uw-ublock|誤導}}' }),
summary: conv({ hans: '封禁通知:误导性用户名', hant: '封鎖通知:誤導性使用者名稱' })
},
'uw-ublock|宣传': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|宣传}}', hant: '{{uw-ublock|宣傳}}' }),
summary: conv({ hans: '封禁通知:宣传性用户名', hant: '封鎖通知:宣傳性使用者名稱' })
},
'uw-ublock|攻击|或侮辱性': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|攻击|或侮辱性}}', hant: '{{uw-ublock|攻擊|或侮辱性}}' }),
summary: conv({ hans: '封禁通知:攻击或侮辱性用户名', hant: '封鎖通知:攻擊或侮辱性使用者名稱' })
},
'uw-ublock|混淆': {
expiry: 'infinity',
reason: '{{uw-ublock|混淆}}',
summary: conv({ hans: '封禁通知:令人混淆的用户名', hant: '封鎖通知:令人混淆的使用者名稱' })
},
'uw-vblock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VAN|破坏]]', hant: '[[WP:VAN|破壞]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN|破坏]]', hant: '封鎖通知:[[WP:VAN|破壞]]' })
},
'uw-voablock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VOA|纯粹破坏]]', hant: '[[WP:VOA|純粹破壞]]' }),
summary: conv({ hans: '封禁通知:您的账户仅用于[[WP:VAN|破坏]]', hant: '封鎖通知:您的帳號僅用於[[WP:VAN|破壞]]' }),
templateName: 'uw-blockindef'
},
'Bot block message': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: conv({ hans: '机器人故障', hant: '機器人故障' }),
summary: conv({ hans: '封禁通知:机器人故障', hant: '封鎖通知:機器人故障' }),
sig: '~~~~'
},
// zhwiki
'vcc-violation': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reasonParam: true,
reason: conv({ hans: '[[WP:VAN#LANG|繁简破坏]]', hant: '[[WP:VAN#LANG|繁簡破壞]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN#LANG|无故替换繁简用字]]', hant: '封鎖通知:[[WP:VAN#LANG|無故替換繁簡用字]]' }),
templateName: 'uw-block'
},
'cross-wiki-van': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '跨维基项目破坏', hant: '跨維基項目破壞' }),
summary: conv({ hans: '封禁通知:跨维基项目[[WP:VAN|破坏]]', hant: '封鎖通知:跨維基項目[[WP:VAN|破壞]]' }),
templateName: 'uw-blockindef'
},
'point-block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reasonParam: true,
reason: conv({ hans: '[[WP:POINT|为了阐释观点而扰乱维基百科]]', hant: '[[WP:POINT|為了闡釋觀點而擾亂維基百科]]' }),
summary: conv({ hans: '封禁通知:[[WP:POINT|为了阐释观点而扰乱维基百科]]', hant: '封鎖通知:[[WP:POINT|為了闡釋觀點而擾亂維基百科]]' }),
templateName: 'uw-block'
},
'game-block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reasonParam: true,
reason: conv({ hans: '[[WP:GAME|游戏维基规则]]', hant: '[[WP:GAME|遊戲維基規則]]' }),
summary: conv({ hans: '封禁通知:[[WP:GAME|游戏维基规则]]', hant: '封鎖通知:[[WP:GAME|遊戲維基規則]]' }),
templateName: 'uw-block'
},
'sock-contribs-anon': {
autoblock: true,
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根据用户贡献确定', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根據使用者貢獻確定' }),
summary: conv({ hans: '封禁通知:[[WP:SOCK|使用其他IP地址绕过封禁]]', hant: '封鎖通知:[[WP:SOCK|使用其他IP位址繞過封鎖]]' }),
templateName: 'uw-ablock'
},
'sock-cu-anon': {
autoblock: true,
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 用户查核确认', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 使用者查核確認' }),
summary: conv({ hans: '封禁通知:[[WP:SOCK|使用其他IP地址绕过封禁]]', hant: '封鎖通知:[[WP:SOCK|使用其他IP位址繞過封鎖]]' }),
templateName: 'uw-ablock'
},
'sock-contribs-reg': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根据用户贡献确定', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根據使用者貢獻確定' }),
summary: conv({ hans: '封禁通知:确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]', hant: '封鎖通知:確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]' }),
templateName: 'uw-blockindef'
},
'sock-cu-reg': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 用户查核确认', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 使用者查核確認' }),
summary: conv({ hans: '封禁通知:确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]', hant: '封鎖通知:確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]' }),
templateName: 'uw-blockindef'
},
// Begin partial block templates, accessed in Twinkle.block.blockGroupsPartial
'uw-pblock': {
autoblock: true,
expiry: '1 day',
nocreate: false,
pageParam: false,
reasonParam: true,
summary: conv({ hans: '封禁通知:您已被禁止编辑维基百科的部分区域', hant: '封鎖通知:您已被禁止編輯維基百科的部分區域' })
}
};
Twinkle.block.transformBlockPresets = function twinkleblockTransformBlockPresets() {
// zhwiki: Merge custom reason
$.each(Twinkle.getPref('customBlockReasonList'), function(_, item) {
var newKey = item.value + '|' + item.label;
Twinkle.block.blockPresetsInfo[newKey] = Object.assign(
{},
{
autoblock: true,
nocreate: true
},
Twinkle.block.blockPresetsInfo[item.value],
{
reason: item.label,
templateName: item.value
}
);
if (Twinkle.block.blockPresetsInfo[item.value] === undefined) {
Twinkle.block.blockPresetsInfo[item.value] = {
pageParam: true,
reasonParam: true,
custom: true
};
}
});
// supply sensible defaults
$.each(Twinkle.block.blockPresetsInfo, function(preset, settings) {
settings.summary = settings.summary || settings.reason;
settings.sig = settings.sig !== undefined ? settings.sig : 'yes';
settings.indefinite = settings.indefinite || Morebits.string.isInfinity(settings.expiry);
if (!Twinkle.block.isRegistered && settings.indefinite) {
settings.expiry = '1 day';
} else {
settings.expiry = settings.expiry || '1 day';
}
// zhwiki
if (!Twinkle.block.isRegistered && ['uw-block', 'uw-blockindef'].indexOf(settings.templateName) > -1) {
settings.templateName = 'uw-ablock';
}
Twinkle.block.blockPresetsInfo[preset] = settings;
});
};
// These are the groups of presets and defines the order in which they appear. For each list item:
// label: <string, the description that will be visible in the dropdown>
// value: <string, the key of a preset in blockPresetsInfo>
// meta: <boolean, show in templates only, zhwiki>
Twinkle.block.blockGroups = [
{
label: conv({ hans: '常见封禁理由', hant: '常見封鎖理由' }),
list: [
{ label: conv({ hans: '通用封禁(自定义理由)', hant: '通用封鎖(自訂理由)' }), value: 'uw-block' },
{ label: conv({ hans: '通用封禁(自定义理由) - IP', hant: '通用封鎖(自訂理由) - IP' }), value: 'uw-ablock' },
{ label: conv({ hans: '通用封禁(自定义理由) - 无限期', hant: '通用封鎖(自訂理由) - 無限期' }), value: 'uw-blockindef' },
{ label: conv({ hans: '破坏', hant: '破壞' }), value: 'uw-vblock', selected: true },
{ label: conv({ hans: '繁简破坏', hant: '繁簡破壞' }), value: 'vcc-violation' },
{ label: conv({ hans: '跨维基项目破坏', hant: '跨維基項目破壞' }), value: 'cross-wiki-van' },
{ label: conv({ hans: '纯粹破坏', hant: '純粹破壞' }), value: 'uw-voablock' },
{ label: conv({ hans: '不断加入垃圾链接', hant: '不斷加入垃圾連結' }), value: 'uw-sblock' },
{ label: conv({ hans: '散发广告/宣传', hant: '散發廣告/宣傳' }), value: 'uw-adblock' },
{ label: conv({ hans: '仅散发广告/宣传', hant: '僅散發廣告/宣傳' }), value: 'uw-soablock' },
{ label: conv({ hans: '违反回退不过三原则', hant: '違反回退不過三原則' }), value: 'uw-3block' },
{ label: conv({ hans: '无礼的行为、人身攻击', hant: '無禮的行為、人身攻擊' }), value: 'uw-pablock' },
{ label: conv({ hans: '骚扰用户', hant: '騷擾使用者' }), value: 'uw-hblock' },
{ label: conv({ hans: '为了阐释观点而扰乱维基百科', hant: '為了闡釋觀點而擾亂維基百科' }), value: 'point-block' },
{ label: conv({ hans: '游戏维基规则', hant: '遊戲維基規則' }), value: 'game-block' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 根据用户贡献确定', hant: '確認為傀儡或真人傀儡 - 根據使用者貢獻確定' }), value: 'sock-contribs-anon' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 用户查核确认', hant: '確認為傀儡或真人傀儡 - 使用者查核確認' }), value: 'sock-contribs-anon' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 根据用户贡献确定', hant: '確認為傀儡或真人傀儡 - 根據使用者貢獻確定' }), value: 'sock-contribs-reg' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 用户查核确认', hant: '確認為傀儡或真人傀儡 - 使用者查核確認' }), value: 'sock-cu-reg' },
{ label: conv({ hans: '滥用多个账户', hant: '濫用多個帳號' }), value: 'uw-sockblock' },
{ label: conv({ hans: '屡次增加没有可靠来源的资料', hant: '屢次增加沒有可靠來源的資料' }), value: 'uw-ucblock' },
{ label: conv({ hans: '在条目中增加无意义文字', hant: '在條目中增加無意義文字' }), value: 'uw-npblock' },
{ label: conv({ hans: '无故删除内容', hant: '無故刪除內容' }), value: 'uw-dblock' },
{ label: conv({ hans: '多次加入侵犯著作权的内容', hant: '多次加入侵犯著作權的內容' }), value: 'uw-copyrightblock' },
{ label: conv({ hans: '机器人发生故障并必须紧急停止', hant: '機器人發生故障並必須緊急停止' }), value: 'Bot block message' },
{ label: conv({ hans: '禁止编辑讨论页', hant: '禁止編輯討論頁' }), value: 'uw-blocknotalk', meta: true }
]
},
{
custom: true,
label: conv({ hans: '自定义封禁理由', hant: '自訂封鎖理由' })
},
{
label: conv({ hans: '用户名封禁', hant: '使用者名稱封鎖' }),
list: [
{ label: conv({ hans: '宣传性用户名、宣传性编辑', hant: '宣傳性使用者名稱、宣傳性編輯' }), value: 'uw-spamublock' },
{ label: conv({ hans: '宣传性用户名、软封禁', hant: '宣傳性使用者名稱、軟封鎖' }), value: 'uw-softerblock' },
{ label: conv({ hans: '用户名与其他用户相似、软封禁', hant: '使用者名稱與其他使用者相似、軟封鎖' }), value: 'uw-ublock-double' },
{ label: conv({ hans: '不当用户名、软封禁', hant: '不當使用者名稱、軟封鎖' }), value: 'uw-ublock' },
{ label: conv({ hans: '用户名试图冒充其他用户、硬封禁', hant: '使用者名稱試圖冒充其他使用者、硬封鎖' }), value: 'uw-uhblock-double' },
{ label: conv({ hans: '用户名与知名人物相似、软封禁', hant: '使用者名稱與知名人物相似、軟封鎖' }), value: 'uw-ublock-wellknown' },
{ label: conv({ hans: '误导性用户名', hant: '誤導性使用者名稱' }), value: 'uw-ublock|误导' },
{ label: conv({ hans: '宣传性用户名', hant: '宣傳性使用者名稱' }), value: 'uw-ublock|宣传' },
{ label: conv({ hans: '攻击性用户名', hant: '攻擊性使用者名稱' }), value: 'uw-ublock|攻击|或侮辱性' },
{ label: conv({ hans: '混淆性用户名', hant: '混淆性使用者名稱' }), value: 'uw-ublock|混淆' }
]
},
{
label: '其他模板',
list: [
{ label: 'anonblock', value: 'anonblock', forAnonOnly: true },
{ label: 'range block', value: 'range block', forAnonOnly: true },
{ label: 'school block', value: 'school block', forAnonOnly: true },
{ label: 'blocked proxy', value: 'blocked proxy', forAnonOnly: true },
{ label: 'CheckUser block', value: 'CheckUser block', forAnonOnly: true },
{ label: 'checkuserblock-account', value: 'checkuserblock-account', forRegisteredOnly: true }
]
}
];
Twinkle.block.blockGroupsPartial = [
{
label: conv({ hans: '常见部分封禁理由', hant: '常見部分封鎖理由' }),
list: [
{ label: conv({ hans: '通用部分封禁(自定义理由)', hant: '通用部分封鎖(自訂理由)' }), value: 'uw-pblock', selected: true }
]
}
];
Twinkle.block.callback.filtered_block_groups = function twinkleblockCallbackFilteredBlockGroups(group, show_template) {
return $.map(group, function(blockGroup) {
// zhwiki: Add custom reason
if (blockGroup.custom) {
if (show_template) {
var templates = $.map(Twinkle.getPref('customBlockReasonList'), function(item) {
if (Twinkle.block.blockPresetsInfo[item.value].custom) {
return item.value;
}
});
templates = Morebits.array.uniq(templates);
blockGroup.list = $.map(templates, function(template) {
return {
label: conv({ hans: '自定义模板', hant: '自訂模板' }),
value: template
};
});
} else {
blockGroup.list = $.map(Twinkle.getPref('customBlockReasonList'), function(item) {
return {
label: item.label,
value: item.value + '|' + item.label
};
});
}
}
var list = $.map(blockGroup.list, function(blockPreset) {
// zhwiki
if (!show_template && blockPreset.meta) {
return;
}
switch (blockPreset.value) {
case 'range block':
if (!Morebits.ip.isRange(relevantUserName)) {
return;
}
blockPreset.selected = !Morebits.ip.get64(relevantUserName);
break;
default:
break;
}
var blockSettings = Twinkle.block.blockPresetsInfo[blockPreset.value];
var registrationRestrict;
if (blockSettings.forRegisteredOnly) {
registrationRestrict = Twinkle.block.isRegistered;
} else if (blockSettings.forAnonOnly) {
registrationRestrict = !Twinkle.block.isRegistered;
} else {
registrationRestrict = true;
}
if (!(blockSettings.templateName && show_template) && registrationRestrict) {
var templateName = blockSettings.templateName || blockPreset.value;
return {
label: (show_template ? '{{' + templateName + '}}: ' : '') + blockPreset.label,
value: blockPreset.value,
data: [{
name: 'template-name',
value: templateName
}],
selected: !!blockPreset.selected,
disabled: !!blockPreset.disabled
};
}
});
if (list.length) {
return {
label: blockGroup.label,
list: list
};
}
});
};
Twinkle.block.callback.change_preset = function twinkleblockCallbackChangePreset(e) {
var form = e.target.form, key = form.preset.value;
if (!key) {
return;
}
Twinkle.block.callback.update_form(e, Twinkle.block.blockPresetsInfo[key]);
if (form.template) {
form.template.value = Twinkle.block.blockPresetsInfo[key].templateName || key;
Twinkle.block.callback.change_template(e);
}
};
Twinkle.block.callback.change_expiry = function twinkleblockCallbackChangeExpiry(e) {
var expiry = e.target.form.expiry;
if (e.target.value === 'custom') {
Morebits.quickForm.setElementVisibility(expiry.parentNode, true);
} else {
Morebits.quickForm.setElementVisibility(expiry.parentNode, false);
expiry.value = e.target.value;
}
};
Twinkle.block.seeAlsos = [];
Twinkle.block.callback.toggle_see_alsos = function twinkleblockCallbackToggleSeeAlso() {
var reason = this.form.reason.value.replace(
new RegExp('(<!-- )(参见|參見)' + Twinkle.block.seeAlsos.join('、') + '( -->)'), ''
);
Twinkle.block.seeAlsos = Twinkle.block.seeAlsos.filter(function(el) {
return el !== this.value;
}.bind(this));
if (this.checked) {
Twinkle.block.seeAlsos.push(this.value);
}
var seeAlsoMessage = Twinkle.block.seeAlsos.join('、');
if (!Twinkle.block.seeAlsos.length) {
this.form.reason.value = reason;
} else {
this.form.reason.value = reason + '<!-- ' + conv({ hans: '参见', hant: '參見' }) + seeAlsoMessage + ' -->';
}
};
// zhwiki: No ds
Twinkle.block.callback.update_form = function twinkleblockCallbackUpdateForm(e, data) {
var form = e.target.form, expiry = data.expiry;
// don't override original expiry if useInitialOptions is set
if (!data.useInitialOptions) {
if (Date.parse(expiry)) {
expiry = new Date(expiry).toGMTString();
form.expiry_preset.value = 'custom';
} else {
form.expiry_preset.value = data.expiry || 'custom';
}
form.expiry.value = expiry;
if (form.expiry_preset.value === 'custom') {
Morebits.quickForm.setElementVisibility(form.expiry.parentNode, true);
} else {
Morebits.quickForm.setElementVisibility(form.expiry.parentNode, false);
}
}
// boolean-flipped options, more at [[mw:API:Block]]
data.disabletalk = data.disabletalk !== undefined ? data.disabletalk : false;
data.hardblock = data.hardblock !== undefined ? data.hardblock : false;
// disable autoblock if blocking a bot
if (Twinkle.block.userIsBot || /bot\b/i.test(relevantUserName)) {
data.autoblock = false;
}
$(form).find('[name=field_block_options]').find(':checkbox').each(function(i, el) {
// don't override original options if useInitialOptions is set
if (data.useInitialOptions && data[el.name] === undefined) {
return;
}
if (el.name === 'closevip') {
return;
}
var check = data[el.name] === '' || !!data[el.name];
$(el).prop('checked', check);
});
if (data.prependReason && data.reason) {
form.reason.value = data.reason + ';' + form.reason.value;
} else {
form.reason.value = data.reason || '';
}
// Clear and/or set any partial page or namespace restrictions
if (form.pagerestrictions) {
var $pageSelect = $(form).find('[name=pagerestrictions]');
var $namespaceSelect = $(form).find('[name=namespacerestrictions]');
// Respect useInitialOptions by clearing data when switching presets
// In practice, this will always clear, since no partial presets use it
if (!data.useInitialOptions) {
$pageSelect.val(null).trigger('change');
$namespaceSelect.val(null).trigger('change');
}
// Add any preset options; in practice, just used for prior block settings
if (data.restrictions) {
if (data.restrictions.pages && !$pageSelect.val().length) {
var pages = data.restrictions.pages.map(function(pr) {
return pr.title;
});
// since page restrictions use an ajax source, we
// short-circuit that and just add a new option
pages.forEach(function(page) {
if (!$pageSelect.find("option[value='" + $.escapeSelector(page) + "']").length) {
var newOption = new Option(page, page, true, true);
$pageSelect.append(newOption);
}
});
$pageSelect.val($pageSelect.val().concat(pages)).trigger('change');
}
if (data.restrictions.namespaces) {
$namespaceSelect.val($namespaceSelect.val().concat(data.restrictions.namespaces)).trigger('change');
}
}
}
};
Twinkle.block.callback.change_template = function twinkleblockcallbackChangeTemplate(e) {
var form = e.target.form, value = form.template.value, settings = Twinkle.block.blockPresetsInfo[value];
var blockBox = $(form).find('[name=actiontype][value=block]').is(':checked');
var partialBox = $(form).find('[name=actiontype][value=partial]').is(':checked');
var templateBox = $(form).find('[name=actiontype][value=template]').is(':checked');
// Block form is not present
if (!blockBox) {
if (settings.indefinite || settings.nonstandard) {
if (Twinkle.block.prev_template_expiry === null) {
Twinkle.block.prev_template_expiry = form.template_expiry.value || '';
}
form.template_expiry.parentNode.style.display = 'none';
form.template_expiry.value = 'infinity';
} else if (form.template_expiry.parentNode.style.display === 'none') {
if (Twinkle.block.prev_template_expiry !== null) {
form.template_expiry.value = Twinkle.block.prev_template_expiry;
Twinkle.block.prev_template_expiry = null;
}
form.template_expiry.parentNode.style.display = 'block';
}
if (Twinkle.block.prev_template_expiry) {
form.expiry.value = Twinkle.block.prev_template_expiry;
}
Morebits.quickForm.setElementVisibility(form.notalk.parentNode, !settings.nonstandard);
// Partial
Morebits.quickForm.setElementVisibility(form.noemail_template.parentNode, partialBox);
Morebits.quickForm.setElementVisibility(form.nocreate_template.parentNode, partialBox);
} else if (templateBox) { // Only present if block && template forms both visible
Morebits.quickForm.setElementVisibility(
form.blank_duration.parentNode,
!settings.indefinite && !settings.nonstandard
);
}
// Only particularly relevant if template form is present
Morebits.quickForm.setElementVisibility(form.article.parentNode, settings && !!settings.pageParam);
Morebits.quickForm.setElementVisibility(form.block_reason.parentNode, settings && !!settings.reasonParam);
// zhwiki: Apply reason from blockPresetsInfo
if (settings.reasonParam) {
form.block_reason.value = Twinkle.block.blockPresetsInfo[form.preset.value].reason || '';
} else {
form.block_reason.value = '';
}
// Partial block
Morebits.quickForm.setElementVisibility(form.area.parentNode, partialBox && !blockBox);
form.root.previewer.closePreview();
};
Twinkle.block.prev_template_expiry = null;
Twinkle.block.callback.preview = function twinkleblockcallbackPreview(form) {
var params = {
article: form.article.value,
blank_duration: form.blank_duration ? form.blank_duration.checked : false,
disabletalk: form.disabletalk.checked || (form.notalk ? form.notalk.checked : false),
expiry: form.template_expiry ? form.template_expiry.value : form.expiry.value,
hardblock: Twinkle.block.isRegistered ? form.autoblock.checked : form.hardblock.checked,
indefinite: Morebits.string.isInfinity(form.template_expiry ? form.template_expiry.value : form.expiry.value),
reason: form.block_reason.value,
template: form.template.value,
partial: $(form).find('[name=actiontype][value=partial]').is(':checked'),
pagerestrictions: $(form.pagerestrictions).val() || [],
namespacerestrictions: $(form.namespacerestrictions).val() || [],
noemail: form.noemail.checked || (form.noemail_template ? form.noemail_template.checked : false),
nocreate: form.nocreate.checked || (form.nocreate_template ? form.nocreate_template.checked : false),
area: form.area.value
};
var templateText = Twinkle.block.callback.getBlockNoticeWikitext(params);
form.previewer.beginRender(templateText, 'User_talk:' + relevantUserName + '/Wikitext'); // Force wikitext/correct username
};
Twinkle.block.callback.evaluate = function twinkleblockCallbackEvaluate(e) {
var params = Morebits.quickForm.getInputData(e.target);
var $form = $(e.target),
toBlock = $form.find('[name=actiontype][value=block]').is(':checked'),
toWarn = $form.find('[name=actiontype][value=template]').is(':checked'),
toPartial = $form.find('[name=actiontype][value=partial]').is(':checked'),
toTag = $form.find('[name=actiontype][value=tag]').is(':checked'),
toProtect = $form.find('[name=actiontype][value=protect]').is(':checked'),
toUnblock = $form.find('[name=actiontype][value=unblock]').is(':checked'),
blockoptions = {}, templateoptions = {}, unblockoptions = {};
Twinkle.block.callback.saveFieldset($form.find('[name=field_block_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_template_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_tag_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_unblock_options]'));
blockoptions = Twinkle.block.field_block_options;
unblockoptions = Twinkle.block.field_unblock_options;
var toClosevip = !!blockoptions.closevip;
templateoptions = Twinkle.block.field_template_options;
templateoptions.disabletalk = !!(templateoptions.disabletalk || blockoptions.disabletalk);
templateoptions.hardblock = !!blockoptions.hardblock;
// remove extraneous
delete blockoptions.expiry_preset;
delete blockoptions.closevip;
// Partial API requires this to be gone, not false or 0
if (toPartial) {
blockoptions.partial = templateoptions.partial = true;
}
templateoptions.pagerestrictions = $form.find('[name=pagerestrictions]').val() || [];
templateoptions.namespacerestrictions = $form.find('[name=namespacerestrictions]').val() || [];
// Format for API here rather than in saveFieldset
blockoptions.pagerestrictions = templateoptions.pagerestrictions.join('|');
blockoptions.namespacerestrictions = templateoptions.namespacerestrictions.join('|');
// use block settings as warn options where not supplied
templateoptions.summary = templateoptions.summary || blockoptions.reason;
templateoptions.expiry = templateoptions.template_expiry || blockoptions.expiry;
// zhwiki
templateoptions.preset = toBlock ? params.preset : null;
// Check tags
// Given an array of incompatible tags, check if we have two or more selected
var checkIncompatible = function(conflicts, extra) {
var count = conflicts.reduce(function(sum, tag) {
return sum += params.tag.indexOf(tag) !== -1;
}, 0);
if (count > 1) {
var message = conv({ hans: '请在以下标签中择一使用', hant: '請在以下標籤中擇一使用' }) + ':{{' + conflicts.join('}}、{{') + '}}。';
message += extra ? extra : '';
alert(message);
return true;
}
};
if (toTag) {
if (params.tag.length === 0) {
return alert(conv({ hans: '请至少选择一个用户页标记!', hant: '請至少選擇一個使用者頁面標記!' }));
}
if (checkIncompatible(['Blocked user', 'Sockpuppet'], conv({ hans: '{{Sockpuppet}}已涵盖{{Blocked user}}的功能。', hant: '{{Sockpuppet}}已涵蓋{{Blocked user}}的功能。' }))) {
return;
}
if (checkIncompatible(['Blocked user', 'Sockpuppeteer'], conv({ hans: '{{Sockpuppeteer}}已涵盖{{Blocked user}}的功能。', hant: '{{Sockpuppeteer}}已涵蓋{{Blocked user}}的功能。' }))) {
return;
}
if (checkIncompatible(['Blocked user', 'Locked global account'], conv({ hans: '请使用{{Locked global account}}的“亦被本地封禁”选项。', hant: '請使用{{Locked global account}}的「亦被本地封鎖」選項。' }))) {
return;
}
if (checkIncompatible(['Sockpuppet', 'Sockpuppeteer'], conv({ hans: '请从主账户和分身账户中选择一个。', hant: '請從主帳號和分身帳號中選擇一個。' }))) {
return;
}
if (params.tag.indexOf('Sockpuppet') > -1 && params.sppUsername.trim() === '') {
return alert(conv({ hans: '请提供傀儡账户的主账户用户名!', hant: '請提供傀儡帳號的主帳號使用者名稱!' }));
}
}
if (toBlock) {
if (blockoptions.partial) {
if (blockoptions.disabletalk && blockoptions.namespacerestrictions.indexOf('3') === -1) {
return alert(conv({ hans: '部分封禁无法阻止编辑自己的讨论页,除非也封禁了User talk命名空间!', hant: '部分封鎖無法阻止編輯自己的討論頁,除非也封鎖了User talk命名空間!' }));
}
if (!blockoptions.namespacerestrictions && !blockoptions.pagerestrictions) {
if (!blockoptions.noemail && !blockoptions.nocreate) { // Blank entries technically allowed [[phab:T208645]]
return alert(conv({ hans: '没有选择页面或命名空间,也没有停用电子邮件或禁止创建账户;请选择至少一个选项以应用部分封禁!', hant: '沒有選擇頁面或命名空間,也沒有停用電子郵件或禁止建立帳號;請選擇至少一個選項以應用部分封鎖!' }));
} else if (!confirm(conv({ hans: '您将要进行封禁,但没有阻止任何页面或命名空间的编辑,确定要继续?', hant: '您將要進行封鎖,但沒有阻止任何頁面或命名空間的編輯,確定要繼續?' }))) {
return;
}
}
}
if (!blockoptions.expiry) {
return alert(conv({ hans: '请提供过期时间!', hant: '請提供過期時間!' }));
} else if (Morebits.string.isInfinity(blockoptions.expiry) && !Twinkle.block.isRegistered) {
return alert(conv({ hans: '禁止无限期封禁IP地址!', hant: '禁止無限期封鎖IP位址!' }));
}
if (!blockoptions.reason) {
return alert(conv({ hans: '请提供封禁理由!', hant: '請提供封鎖理由!' }));
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var statusElement = new Morebits.status(conv({ hans: '执行封禁', hant: '執行封鎖' }));
blockoptions.action = 'block';
blockoptions.user = relevantUserName;
// boolean-flipped options
blockoptions.anononly = blockoptions.hardblock ? undefined : true;
blockoptions.allowusertalk = blockoptions.disabletalk ? undefined : true;
/*
Check if block status changed while processing the form.
There's a lot to consider here. list=blocks provides the
current block status, but there are at least two issues with
relying on it. First, the id doesn't update on a reblock,
meaning the individual parameters need to be compared. This
can be done roughly with JSON.stringify - we can thankfully
rely on order from the server, although sorting would be
fine if not - but falsey values are problematic and is
non-ideal. More importantly, list=blocks won't indicate if a
non-blocked user is blocked then unblocked. This should be
exceedingy rare, but regardless, we thus need to check
list=logevents, which has a nicely updating logid
parameter. We can't rely just on that, though, since it
doesn't account for blocks that have expired on their own.
As such, we use both. Using some ternaries, the logid
variables are false if there's no logevents, so if they
aren't equal we defintely have a changed entry (send
confirmation). If they are equal, then either the user was
never blocked (the block statuses will be equal, no
confirmation) or there's no new block, in which case either
a block expired (different statuses, confirmation) or the
same block is still active (same status, no confirmation).
*/
var query = {
format: 'json',
action: 'query',
list: 'blocks|logevents',
letype: 'block',
lelimit: 1,
letitle: 'User:' + blockoptions.user
};
// bkusers doesn't catch single IPs blocked as part of a range block
if (mw.util.isIPAddress(blockoptions.user, true)) {
query.bkip = blockoptions.user;
} else {
query.bkusers = blockoptions.user;
query.list += '|users';
query.usprop = 'groups';
query.ususers = blockoptions.user;
query.meta = 'tokens';
query.type = 'userrights';
}
api.get(query).then(function(data) {
var block = data.query.blocks[0];
// As with the initial data fetch, if an IP is blocked
// *and* rangeblocked, this would only grab whichever
// block is more recent, which would likely mean a
// mismatch. However, if the rangeblock is updated
// while filling out the form, this won't detect that,
// but that's probably fine.
if (data.query.blocks.length > 1 && block.user !== relevantUserName) {
block = data.query.blocks[1];
}
var logevents = data.query.logevents[0];
var user = data.query.users ? data.query.users[0] : null;
var logid = data.query.logevents.length ? logevents.logid : false;
if (logid !== Twinkle.block.blockLogId || !!block !== !!Twinkle.block.currentBlockInfo) {
var message = blockoptions.user + conv({ hans: '的封禁状态已被修改。', hant: '的封鎖狀態已被修改。' });
if (block) {
message += conv({ hans: '新状态:', hant: '新狀態:' });
} else {
message += conv({ hans: '最新日志:', hant: '最新日誌:' });
}
var logExpiry = '';
if (logevents.params.duration) {
if (logevents.params.duration === 'infinity') {
logExpiry = conv({ hans: '无限期', hant: '無限期' });
} else {
var expiryDate = new Morebits.date(logevents.params.expiry);
logExpiry += (expiryDate.isBefore(new Date()) ? conv({ hans: '过期于', hant: '過期於' }) : '直到') + expiryDate.calendar();
}
} else { // no duration, action=unblock, just show timestamp
logExpiry = '於' + new Morebits.date(logevents.timestamp).calendar();
}
message += '由' + logevents.user + conv({ hans: '以“', hant: '以「' }) + logevents.comment + conv({ hans: '”', hant: '」' }) +
blockActionText[logevents.action] + logExpiry + conv({ hans: ',你想要以你的设置变更封禁吗?', hant: ',你想要以你的設定變更封鎖嗎?' });
if (!confirm(message)) {
Morebits.status.info(conv({ hans: '执行封禁', hant: '執行封鎖' }), conv({ hans: '用户取消操作', hant: '使用者取消操作' }));
return;
}
blockoptions.reblock = 1; // Writing over a block will fail otherwise
}
var groupsCanBeRemoved = [
'autoreviewer',
'confirmed',
'eventparticipant',
'filemover',
'ipblock-exempt',
'massmessage-sender',
'patroller',
'rollbacker',
'templateeditor',
'transwiki'
];
var groupsToBeRemoved = [];
if (user && Morebits.string.isInfinity(blockoptions.expiry)) {
groupsToBeRemoved = user.groups.filter(function (group) {
return groupsCanBeRemoved.indexOf(group) > -1;
});
}
// execute block
blockoptions.tags = Twinkle.changeTags;
blockoptions.token = mw.user.tokens.get('csrfToken');
var mbApi = new Morebits.wiki.api(conv({ hans: '执行封禁', hant: '執行封鎖' }), blockoptions, function () {
statusElement.info('完成');
if (toWarn) {
Twinkle.block.callback.issue_template(templateoptions);
}
if (toClosevip) {
var vipPage = new Morebits.wiki.page('Wikipedia:当前的破坏', conv({ hans: '关闭请求', hant: '關閉請求' }));
vipPage.setFollowRedirect(true);
vipPage.setCallbackParameters(blockoptions);
vipPage.load(Twinkle.block.callback.closeRequest);
}
if (groupsToBeRemoved.length > 0) {
var rightStatusElement = new Morebits.status(conv({ hans: '移除权限', hant: '移除權限' }));
if (confirm(conv({ hans: '该用户有以下权限:', hant: '該使用者有以下權限:' }) + groupsToBeRemoved.join('、') + conv({ hans: ',您是否想要同时移除这些权限?', hant: ',您是否想要同時移除這些權限?' }))) {
var revokeOptions = {
action: 'userrights',
user: blockoptions.user,
remove: groupsToBeRemoved.join('|'),
reason: conv({ hans: '用户已被无限期封禁', hant: '使用者已被無限期封鎖' }),
token: data.query.tokens.userrightstoken,
tags: Twinkle.changeTags
};
var mrApi = new Morebits.wiki.api(conv({ hans: '移除权限', hant: '移除權限' }), revokeOptions, function () {
rightStatusElement.info('已移除' + groupsToBeRemoved.join('、'));
});
mrApi.post();
} else {
rightStatusElement.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
}
}
});
mbApi.post();
});
} else if (toWarn) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Twinkle.block.callback.issue_template(templateoptions);
}
if (toTag || toProtect) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var userPage = 'User:' + Morebits.wiki.flow.relevantUserName(true);
var wikipedia_page = new Morebits.wiki.page(userPage, conv({ hans: '标记或保护用户页', hant: '標記或保護使用者頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.block.callback.taguserpage);
}
if (toUnblock) {
if (!unblockoptions.reason) {
return alert(conv({ hans: '请提供解除封禁理由!', hant: '請提供解除封鎖理由!' }));
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var unblockStatusElement = new Morebits.status(conv({ hans: '执行解除封禁', hant: '執行解除封鎖' }));
unblockoptions.action = 'unblock';
unblockoptions.user = Morebits.wiki.flow.relevantUserName(true);
// execute unblock
unblockoptions.tags = Twinkle.changeTags;
unblockoptions.token = mw.user.tokens.get('csrfToken');
var unblockMbApi = new Morebits.wiki.api(conv({ hans: '执行解除封禁', hant: '執行解除封鎖' }), unblockoptions, function () {
unblockStatusElement.info('完成');
});
unblockMbApi.post();
}
if (!toBlock && !toWarn && !toTag && !toProtect && !toUnblock) {
return alert(conv({ hans: '请给Twinkle点事做!', hant: '請給Twinkle點事做!' }));
}
};
Twinkle.block.callback.taguserpage = function twinkleblockCallbackTagUserpage(pageobj) {
var params = pageobj.getCallbackParameters();
var statelem = pageobj.getStatusElement();
if (params.actiontype.indexOf('tag') > -1) {
var tags = [];
params.tag.forEach(function(tag) {
var tagtext = '{{' + tag;
switch (tag) {
case 'Blocked user':
break;
case 'Sockpuppet':
tagtext += '\n| 1 = ' + params.sppUsername.trim();
tagtext += '\n| 2 = ' + params.sppType.trim();
if (params.sppEvidence.trim()) {
tagtext += '\n| evidence = ' + params.sppEvidence.trim();
}
tagtext += '\n| locked = no';
tagtext += '\n| notblocked = no';
tagtext += '\n';
break;
case 'Sockpuppeteer':
tagtext += '\n| 1 = blocked';
tagtext += '\n| checked = ' + (params.spmChecked ? 'yes' : '');
if (params.spmEvidence.trim()) {
tagtext += '\n| evidence = ' + params.spmEvidence.trim();
}
tagtext += '\n';
break;
case 'Locked global account':
if (params.lockBlocked) {
tagtext += '|blocked=yes';
}
break;
default:
return alert(conv({ hans: '未知的用户页模板!', hant: '未知的使用者頁面模板!' }));
}
tagtext += '}}';
tags.push(tagtext);
});
var text = tags.join('\n');
if (params.category) {
text += '\n[[Category:' + params.category.trim() + '的維基用戶分身]]';
}
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '标记被永久封禁的用户页', hant: '標記被永久封鎖的使用者頁面' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.save(function() {
Morebits.status.info(conv({ hans: '标记用户页', hant: '標記使用者頁面' }), '完成');
statelem.status(conv({ hans: '正在保护页面', hant: '正在保護頁面' }));
pageobj.load(Twinkle.block.callback.protectuserpage);
});
} else {
Twinkle.block.callback.protectuserpage(pageobj);
}
};
Twinkle.block.callback.protectuserpage = function twinkleblockCallbackProtectUserpage(pageobj) {
var params = pageobj.getCallbackParameters();
var statelem = pageobj.getStatusElement();
if (params.actiontype.indexOf('protect') > -1) {
if (pageobj.exists()) {
pageobj.setEditProtection('sysop', 'indefinite');
pageobj.setMoveProtection('sysop', 'indefinite');
} else {
pageobj.setCreateProtection('sysop', 'indefinite');
}
pageobj.setEditSummary(conv({ hans: '被永久封禁的用户页', hant: '被永久封鎖的使用者頁面' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.protect(function() {
Morebits.status.info(conv({ hans: '保护用户页', hant: '保護使用者頁面' }), pageobj.exists() ? conv({ hans: '已全保护', hant: '已全保護' }) : conv({ hans: '已白纸保护', hant: '已白紙保護' }));
statelem.info('全部完成');
});
} else {
statelem.info('全部完成');
}
};
Twinkle.block.callback.issue_template = function twinkleblockCallbackIssueTemplate(formData) {
// Use wgRelevantUserName to ensure the block template goes to a single IP and not to the
// "talk page" of an IP range (which does not exist)
var userTalkPage = 'User_talk:' + Morebits.wiki.flow.relevantUserName(true);
var params = $.extend(formData, {
messageData: Twinkle.block.blockPresetsInfo[formData.template],
usertalk_summary: Twinkle.block.blockPresetsInfo[formData.preset || formData.template].summary, // zhwiki
reason: Twinkle.block.field_template_options.block_reason,
disabletalk: Twinkle.block.field_template_options.notalk,
noemail: Twinkle.block.field_template_options.noemail_template,
nocreate: Twinkle.block.field_template_options.nocreate_template
});
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '完成,将在几秒后加载用户讨论页', hant: '完成,將在幾秒後載入使用者討論頁' });
Morebits.wiki.flow.check(userTalkPage, function () {
var flowpage = new Morebits.wiki.flow(userTalkPage, conv({ hans: '用户Flow讨论页留言', hant: '使用者Flow討論頁留言' }));
flowpage.setCallbackParameters(params);
Twinkle.block.callback.main_flow(flowpage);
}, function () {
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '用户讨论页修改', hant: '使用者討論頁修改' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.block.callback.main);
});
};
Twinkle.block.callback.closeRequest = function twinkleblockCallbackCloseRequest(vipPage) {
var params = vipPage.getCallbackParameters();
var text = vipPage.getPageText();
var statusElement = vipPage.getStatusElement();
var userName = Morebits.wiki.flow.relevantUserName(true);
var expiryText = Morebits.string.formatTime(params.expiry);
var comment = '{{Blocked|' + (Morebits.string.isInfinity(params.expiry) ? 'indef' : expiryText) + '}}。';
var requestList = text.split(/(?=\n===.+===\s*\n)/);
var found = false;
var hidename = false;
var vipRe = new RegExp('{{\\s*[Vv]andal\\s*\\|\\s*(1\\s*=\\s*)?' + Morebits.pageNameRegex(userName) + '\\s*(\\|\\s*hidename\\s*=[^|]+)?}}', 'm');
for (var i = 1; i < requestList.length; i++) {
if (vipRe.exec(requestList[i])) {
hidename = /\|\s*hidename\s*=[^|]+/.test(requestList[i]);
requestList[i] = requestList[i].trimRight();
var newText = requestList[i].replace(/^(\*\s*处理:)[ \t]*(<!-- 非管理員僅可標記已執行的封禁,針對提報的意見請放在下一行 -->)?[ \t]*$/m, '$1' + comment + '--~~~~');
if (requestList[i] === newText) {
newText = requestList[i] + '\n* 处理:' + comment + '--~~~~';
}
requestList[i] = newText + '\n';
found = true;
break;
}
}
if (!found) {
statusElement.warn(conv({ hans: '没有找到相关的请求', hant: '沒有找到相關的請求' }));
return;
}
text = requestList.join('');
var summary;
if (hidename) {
summary = conv({ hans: '标记为已处理', hant: '標記為已處理' });
} else {
summary = '/* ' + userName + ' */ ';
if (Morebits.string.isInfinity(params.expiry)) {
summary += conv({ hans: '不限期封禁', hant: '不限期封鎖' });
} else {
summary += conv({ hans: '封禁', hant: '封鎖' }) + expiryText;
}
}
vipPage.setEditSummary(summary);
vipPage.setChangeTags(Twinkle.changeTags);
vipPage.setPageText(text);
vipPage.save();
};
Twinkle.block.callback.getBlockNoticeWikitext = function(params) {
var text = '{{', settings = Twinkle.block.blockPresetsInfo[params.template];
if (!settings.nonstandard) {
text += 'subst:' + params.template;
if (params.article && settings.pageParam) {
text += '|page=' + params.article;
}
if (!/te?mp|^\s*$|min/.exec(params.expiry)) {
if (params.indefinite) {
text += '|indef=yes';
} else if (!params.blank_duration) { // zhwiki: No expiry checks
// Block template wants a duration, not date
text += '|time=' + Morebits.string.formatTime(params.expiry); // zhwiki: formatTime
}
}
if (!Twinkle.block.isRegistered && !params.hardblock) {
text += '|anon=yes';
}
if (params.reason) {
text += '|reason=' + params.reason;
}
if (params.disabletalk) {
text += '|notalk=yes';
}
// Currently, all partial block templates are "standard"
// Building the template, however, takes a fair bit of logic
if (params.partial) {
if (params.pagerestrictions.length || params.namespacerestrictions.length) {
var makeSentence = function (array) {
if (array.length < 3) {
return array.join('和');
}
var last = array.pop();
return array.join('、') + '和' + last;
};
text += '|area=某些';
if (params.pagerestrictions.length) {
text += '頁面(' + makeSentence(params.pagerestrictions.map(function(p) {
return '[[:' + p + ']]';
}));
text += params.namespacerestrictions.length ? ')和某些' : ')';
}
if (params.namespacerestrictions.length) {
// 1 => Talk, 2 => User, etc.
var namespaceNames = params.namespacerestrictions.map(function(id) {
return menuFormattedNamespaces[id];
});
text += conv({ hans: '[[Wikipedia:命名空间|命名空间]](', hant: '[[Wikipedia:命名空間|命名空間]](' }) + makeSentence(namespaceNames) + ')';
}
} else if (params.area) {
text += '|area=' + params.area;
} else {
if (params.noemail) {
text += '|email=yes';
}
if (params.nocreate) {
text += '|accountcreate=yes';
}
}
}
} else {
text += params.template;
}
if (settings.sig) {
text += '|sig=' + settings.sig;
}
return text + '}}';
};
Twinkle.block.callback.main = function twinkleblockcallbackMain(pageobj) {
var params = pageobj.getCallbackParameters(),
date = new Morebits.date(pageobj.getLoadTime()),
messageData = params.messageData,
text;
params.indefinite = Morebits.string.isInfinity(params.expiry);
if (Twinkle.getPref('blankTalkpageOnIndefBlock') && params.template !== 'uw-lblock' && params.indefinite) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '根据参数设置清空讨论页并为日期创建新2级标题', hant: '根據偏好設定清空討論頁並為日期建立新2級標題' }));
text = date.monthHeader() + '\n';
} else {
text = pageobj.getPageText();
var dateHeaderRegex = date.monthHeaderRegex(), dateHeaderRegexLast, dateHeaderRegexResult;
while ((dateHeaderRegexLast = dateHeaderRegex.exec(text)) !== null) {
dateHeaderRegexResult = dateHeaderRegexLast;
}
// If dateHeaderRegexResult is null then lastHeaderIndex is never checked. If it is not null but
// \n== is not found, then the date header must be at the very start of the page. lastIndexOf
// returns -1 in this case, so lastHeaderIndex gets set to 0 as desired.
var lastHeaderIndex = text.lastIndexOf('\n==') + 1;
if (text.length > 0) {
text += '\n\n';
}
if (!dateHeaderRegexResult || dateHeaderRegexResult.index !== lastHeaderIndex) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '未找到当月的二级标题,将创建新的', hant: '未找到當月的二級標題,將建立新的' }));
text += date.monthHeader() + '\n';
}
}
params.expiry = typeof params.template_expiry !== 'undefined' ? params.template_expiry : params.expiry;
text += Twinkle.block.callback.getBlockNoticeWikitext(params);
// build the edit summary
var summary = params.usertalk_summary; // zhwiki
if (messageData.suppressArticleInSummary !== true && params.article) {
summary += conv({ hans: ',于', hant: ',於' }) + '[[:' + params.article + ']]';
}
pageobj.setPageText(text);
pageobj.setEditSummary(summary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchBlockNotices'));
pageobj.save();
};
Twinkle.block.callback.main_flow = function twinkleblockcallbackMain(flowobj) {
var params = flowobj.getCallbackParameters();
params.indefinite = (/indef|infinity|never|\*|max/).test(params.expiry);
params.expiry = typeof params.template_expiry !== 'undefined' ? params.template_expiry : params.expiry;
var title = params.usertalk_summary;
var content = Twinkle.block.callback.getBlockNoticeWikitext(params, true);
flowobj.setTopic(title);
flowobj.setContent(content);
flowobj.newTopic();
};
Twinkle.addInitCallback(Twinkle.block, 'block');
})(jQuery);
// </nowiki>
35692362783ed37f234ff1f822feb40f5d728d8d
MediaWiki:Gadget-twinklecopyvio.js
8
157
316
2023-11-06T13:17:17Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) { // eslint-disable-line no-unused-vars
/*
****************************************
*** twinklecopyvio.js: Copyvio module
****************************************
* Mode of invocation: Tab ("Copyvio")
* Active on: Existing, non-special pages, except for file pages with no local (non-Commons) file which are not redirects
* Config directives in: TwinkleConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.copyvio = function twinklecopyvio() {
// Disable on:
// * special pages
// * non-existent pages
// * files on Commons, whether there is a local page or not (unneeded local pages of files on Commons are eligible for CSD F2)
// * file pages without actual files (these are eligible for CSD G8)
if (mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && (document.getElementById('mw-sharedupload') || (!document.getElementById('mw-imagepage-section-filehistory') && !Morebits.isPageRedirect())))) {
return;
}
if (mw.config.get('wgPageContentModel') === 'flow-board') {
return;
}
Twinkle.addPortletLink(Twinkle.copyvio.callback, conv({ hans: '侵权', hant: '侵權' }), 'tw-copyvio', conv({ hans: '提报侵权页面', hant: '提報侵權頁面' }), '');
};
Twinkle.copyvio.callback = function twinklecopyvioCallback() {
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '提报侵权页面', hant: '提報侵權頁面' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '常见错误', hant: '常見錯誤' }), 'Wikipedia:管理员错误自查表/侵权处理');
Window.addFooterLink(conv({ hans: '侵权设置', hant: '侵權設定' }), 'WP:TW/PREF#copyvio');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#copyvio');
var form = new Morebits.quickForm(Twinkle.copyvio.callback.evaluate);
form.append({
type: 'textarea',
label: conv({ hans: '侵权来源:', hant: '侵權來源:' }),
name: 'source'
}
);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: 'CSD G5: 曾经根据侵权审核删除后又重新创建的内容', hant: 'CSD G5: 曾經根據侵權審核刪除後又重新建立的內容' }),
value: 'g5',
name: 'g5',
tooltip: conv({ hans: '同时以G5准则提报快速删除', hant: '同時以G5準則提報快速刪除' }),
subgroup: [{
name: 'g5_pagename',
type: 'input',
label: conv({ hans: '前次删除的页面名称', hant: '前次刪除的頁面名稱' }),
tooltip: conv({ hans: '选填,如果前次删除的页面名称不同,请提供', hant: '選填,如果前次刪除的頁面名稱不同,請提供' })
}]
},
{
label: conv({ hans: 'CSD G16: 页面与介绍相同事物的原页面同样侵权', hant: 'CSD G16: 頁面與介紹相同事物的原頁面同樣侵權' }),
value: 'g16',
name: 'g16',
tooltip: conv({ hans: '同时以G16准则提报快速删除', hant: '同時以G16準則提報快速刪除' }),
subgroup: [{
name: 'g16_pagename',
type: 'input',
label: conv({ hans: '已提报侵权的页面名称', hant: '已提報侵權的頁面名稱' }),
tooltip: conv({ hans: '必填,请提供当前正在侵权审核的页面名称,若页面已根据侵权删除,则应使用G5准则', hant: '必填,請提供目前正在侵權審核的頁面名稱,若頁面已根據侵權刪除,則應使用G5準則' })
}]
},
{
label: conv({ hans: '通知页面创建者', hant: '通知頁面建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '在页面创建者讨论页上放置一通知模板。', hant: '在頁面建立者討論頁上放置一通知模板。' }),
checked: true
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
};
Twinkle.copyvio.callbacks = {
tryTagging: function (pageobj) {
// 先尝试标记页面,如果发现已经标记则停止提报
var text = pageobj.getPageText();
if (text.indexOf('{{Copyvio|') === -1) {
Twinkle.copyvio.callbacks.taggingArticle(pageobj);
// Contributor specific edits
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'));
wikipedia_page.setCallbackParameters(pageobj.getCallbackParameters());
wikipedia_page.lookupCreation(Twinkle.copyvio.callbacks.main);
} else {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '页面已经标记侵权,请人工确认是否已经提报。', hant: '頁面已經標記侵權,請人工確認是否已經提報。' }));
}
},
main: function(pageobj) {
// this is coming in from lookupCreation...!
var params = pageobj.getCallbackParameters();
var initialContrib = pageobj.getCreator();
// Adding discussion
var wikipedia_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入侵权记录项', hant: '加入侵權記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.copyvio.callbacks.copyvioList);
// Notification to first contributor
if (params.notify) {
Morebits.wiki.flow.check('User talk:' + initialContrib, function () {
var flowpage = new Morebits.wiki.flow('User talk:' + initialContrib, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
var topic = '您建立的页面[[' + mw.config.get('wgPageName') + ']]可能侵犯版权';
var content = '{{subst:CopyvioNotice|' + mw.config.get('wgPageName') + '|flow=yes}}';
flowpage.setTopic(topic);
flowpage.setContent(content);
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
var notifytext = '\n{{subst:CopyvioNotice|' + mw.config.get('wgPageName') + '}}';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(conv({ hans: '通知:页面[[', hant: '通知:頁面[[' }) + mw.config.get('wgPageName') + conv({ hans: ']]疑似侵犯著作权', hant: ']]疑似侵犯版權' }));
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('copyvioWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
},
taggingArticle: function(pageobj) {
var params = pageobj.getCallbackParameters();
var revisionId = mw.config.get('wgRevisionId') || mw.config.get('wgDiffNewId') || mw.config.get('wgCurRevisionId');
var tag = '{{subst:Copyvio/auto|url=' + params.source.replace(/http/g, 'http').replace(/\n+/g, '\n').replace(/^\s*([^*])/gm, '* $1').replace(/^\* $/m, '') + '|OldRevision=' + revisionId + '}}';
var text = pageobj.getPageText();
var oldcsd = text.match(/{{\s*(db(-\w*)?|d|delete)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}/i);
if (oldcsd && confirm(conv({ hans: '在页面上找到快速删除模板,要保留吗?\n\n当页面同时侵犯著作权又符合快速删除标准时,应该优先走快速删除程序。\n单击“确认”以保留快速删除模板,若您认为快速删除理由不合,单击“取消”以移除快速删除模板。', hant: '在頁面上找到快速刪除模板,要保留嗎?\n\n當頁面同時侵犯版權又符合快速刪除標準時,應該優先走快速刪除程序。\n點擊「確認」以保留快速刪除模板,若您認為快速刪除理由不合,點擊「取消」以移除快速刪除模板。' }))) {
tag = oldcsd[0] + '\n' + tag;
var oldsalt = text.match(/{{\s*salt\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}/i);
if (oldsalt) {
tag = oldsalt[0] + '\n' + tag;
}
}
if (params.g5 || params.g16) {
var speedyTag = '{{delete';
if (params.g5) {
speedyTag += '|g5';
if (params.g5_pagename) {
speedyTag += '|' + params.g5_pagename + '|c1=[[Special:Undelete/' + params.g5_pagename + ']]';
} else {
speedyTag += '|c1=[[Special:Undelete/' + mw.config.get('wgPageName') + ']]';
}
}
if (params.g16) {
speedyTag += '|g16|' + params.g16_pagename;
}
speedyTag += '}}';
tag = speedyTag + '\n' + tag;
}
pageobj.setPageText(tag);
pageobj.setEditSummary(conv({ hans: '本页面疑似侵犯著作权', hant: '本頁面疑似侵犯版權' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('copyvioWatchPage'));
// pageobj.setCreateOption('recreate');
pageobj.save();
if (Twinkle.getPref('markCopyvioPagesAsPatrolled')) {
pageobj.patrol();
}
},
copyvioList: function(pageobj) {
var text = pageobj.getPageText();
var output = '';
var date = new Date();
var dateHeaderRegex = new RegExp('^===+\\s*' + (date.getUTCMonth() + 1) + '月' + date.getUTCDate() + '日' +
'\\s*===+', 'mg');
if (!dateHeaderRegex.exec(text)) {
output = '\n\n===' + (date.getUTCMonth() + 1) + '月' + date.getUTCDate() + '日' + '===';
}
output += '\n{{subst:CopyvioVFDRecord|' + mw.config.get('wgPageName') + '}}';
pageobj.setAppendText(output);
pageobj.setEditSummary('加入[[' + mw.config.get('wgPageName') + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
}
};
Twinkle.copyvio.callback.evaluate = function(e) {
var params = Morebits.quickForm.getInputData(e.target);
if (!params.source.trim()) {
alert(conv({ hans: '请指定侵权来源', hant: '請指定侵權來源' }));
return;
}
if (params.g16 && !params.g16_pagename.trim()) {
alert(conv({ hans: '请提供G16已提报侵权的页面名称', hant: '請提供G16已提報侵權的頁面名稱' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
params.logpage = 'Wikipedia:頁面存廢討論/疑似侵權';
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '提报完成,将在几秒内刷新页面', hant: '提報完成,將在幾秒內重新整理頁面' });
// Tagging file
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入侵权模板到页面', hant: '加入侵權模板到頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.copyvio.callbacks.tryTagging);
Morebits.wiki.removeCheckpoint();
};
Twinkle.addInitCallback(Twinkle.copyvio, 'copyvio');
})(jQuery);
// </nowiki>
75a468d750ba5fdcaadc0ac92f4437b7e01f7840
MediaWiki:Gadget-twinklediff.js
8
163
328
2023-11-06T13:17:19Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklediff.js: Diff module
****************************************
* Mode of invocation: Tab on non-diff pages ("Last"); tabs on diff pages ("Since", "Since mine", "Current")
* Active on: Existing non-special pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.diff = function twinklediff() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
return;
}
Twinkle.addPortletLink(mw.util.getUrl(mw.config.get('wgPageName'), { diff: 'cur', oldid: 'prev' }), conv({ hans: '最后', hant: '最後' }), 'tw-lastdiff', conv({ hans: '显示最后修改', hant: '顯示最後修改' }));
// Show additional tabs only on diff pages
if (mw.config.get('wgDiffNewId')) {
Twinkle.addPortletLink(function() {
Twinkle.diff.evaluate(false);
}, '自上', 'tw-since', conv({ hans: '显示与上一修订版本间的差异', hant: '顯示與上一修訂版本間的差異' }));
Twinkle.addPortletLink(function() {
Twinkle.diff.evaluate(true);
}, '自我', 'tw-sincemine', conv({ hans: '显示与我做出的修订版本的差异', hant: '顯示與我做出的修訂版本的差異' }));
Twinkle.addPortletLink(mw.util.getUrl(mw.config.get('wgPageName'), { diff: 'cur', oldid: mw.config.get('wgDiffNewId') }), conv({ hans: '当前', hant: '目前' }), 'tw-curdiff', conv({ hans: '显示与当前版本间的差异', hant: '顯示與目前版本間的差異' }));
}
};
Twinkle.diff.evaluate = function twinklediffEvaluate(me) {
var user;
if (me) {
user = mw.config.get('wgUserName');
} else {
var node = document.getElementById('mw-diff-ntitle2');
if (!node) {
// nothing to do?
return;
}
user = $(node).find('a').first().text();
}
var query = {
prop: 'revisions',
action: 'query',
titles: mw.config.get('wgPageName'),
rvlimit: 1,
rvprop: [ 'ids', 'user' ],
rvstartid: mw.config.get('wgCurRevisionId') - 1, // i.e. not the current one
rvuser: user
};
Morebits.status.init(document.getElementById('mw-content-text'));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取最初贡献者信息', hant: '抓取最初貢獻者資訊' }), query, Twinkle.diff.callbacks.main);
wikipedia_api.params = { user: user };
wikipedia_api.post();
};
Twinkle.diff.callbacks = {
main: function(self) {
var xmlDoc = self.responseXML;
var revid = $(xmlDoc).find('rev').attr('revid');
if (!revid) {
self.statelem.error(conv({ hans: '未找到合适的早期版本,或 ', hant: '未找到合適的早期版本,或 ' }) + self.params.user + conv({ hans: ' 是唯一贡献者。取消。', hant: ' 是唯一貢獻者。取消。' }));
return;
}
window.location = mw.util.getUrl(mw.config.get('wgPageName'), {
diff: mw.config.get('wgCurRevisionId'),
oldid: revid
});
}
};
Twinkle.addInitCallback(Twinkle.diff, 'diff');
})(jQuery);
// </nowiki>
67886f369cd2fca278e97a889516799a7e6e7ed2
MediaWiki:Gadget-twinklefluff.js
8
165
332
2023-11-06T13:17:22Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklefluff.js: Revert/rollback module
****************************************
* Mode of invocation: Links on contributions, recent changes, history, and diff pages
* Active on: Diff pages, history pages, Special:RecentChanges(Linked),
and Special:Contributions
*/
/**
Twinklefluff revert and antivandalism utility
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.fluff = function twinklefluff() {
// Only proceed if the user can actually edit the page in question
// (see #632 for contribs issue). wgIsProbablyEditable should take
// care of namespace/contentModel restrictions as well as explicit
// protections; it won't take care of cascading or TitleBlacklist.
if (mw.config.get('wgIsProbablyEditable')) {
// wgDiffOldId included for clarity in if else loop [[phab:T214985]]
if (mw.config.get('wgDiffNewId') || mw.config.get('wgDiffOldId')) {
// Reload alongside the revision slider
mw.hook('wikipage.diff').add(function () {
Twinkle.fluff.addLinks.diff();
});
} else if (mw.config.get('wgAction') === 'view' && mw.config.get('wgRevisionId') && mw.config.get('wgCurRevisionId') !== mw.config.get('wgRevisionId')) {
Twinkle.fluff.addLinks.oldid();
} else if (mw.config.get('wgAction') === 'history') {
Twinkle.fluff.addLinks.history();
}
} else if (mw.config.get('wgNamespaceNumber') === -1) {
Twinkle.fluff.skipTalk = !Twinkle.getPref('openTalkPageOnAutoRevert');
Twinkle.fluff.rollbackInPlace = Twinkle.getPref('rollbackInPlace');
if (mw.config.get('wgCanonicalSpecialPageName') === 'Contributions') {
Twinkle.fluff.addLinks.contributions();
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'Recentchanges' || mw.config.get('wgCanonicalSpecialPageName') === 'Recentchangeslinked') {
// Reload with recent changes updates
// structuredChangeFilters.ui.initialized is just on load
mw.hook('wikipage.content').add(function(item) {
if (item.is('div')) {
Twinkle.fluff.addLinks.recentchanges();
}
});
}
}
};
// A list of usernames, usually only bots, that vandalism revert is jumped
// over; that is, if vandalism revert was chosen on such username, then its
// target is on the revision before. This is for handling quick bots that
// makes edits seconds after the original edit is made. This only affects
// vandalism rollback; for good faith rollback, it will stop, indicating a bot
// has no faith, and for normal rollback, it will rollback that edit.
Twinkle.fluff.trustedBots = [
'Antigng-bot',
'Jimmy-bot',
'Jimmy-abot',
'Liangent-bot',
'Liangent-adminbot',
'Cewbot',
'WhitePhosphorus-bot'
];
Twinkle.fluff.skipTalk = null;
Twinkle.fluff.rollbackInPlace = null;
// String to insert when a username is hidden
Twinkle.fluff.hiddenName = conv({ hans: '已隐藏的用户', hant: '已隱藏的使用者' });
// Consolidated construction of fluff links
Twinkle.fluff.linkBuilder = {
spanTag: function(color, content) {
var span = document.createElement('span');
span.style.color = color;
span.appendChild(document.createTextNode(content));
return span;
},
buildLink: function(color, text) {
var link = document.createElement('a');
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', '['));
link.appendChild(Twinkle.fluff.linkBuilder.spanTag(color, text));
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', ']'));
link.href = '#';
return link;
},
/**
* @param {string} [vandal=null] - Username of the editor being reverted
* Provide a falsey value if the username is hidden, defaults to null
* @param {boolean} inline - True to create two links in a span, false
* to create three links in a div (optional)
* @param {number|string} [rev=wgCurRevisionId] - Revision ID being reverted (optional)
* @param {string} [page=wgPageName] - Page being reverted (optional)
*/
rollbackLinks: function(vandal, inline, rev, page) {
vandal = vandal || null;
var elem = inline ? 'span' : 'div';
var revNode = document.createElement(elem);
rev = parseInt(rev, 10);
if (rev) {
revNode.setAttribute('id', 'tw-revert' + rev);
} else {
revNode.setAttribute('id', 'tw-revert');
}
var normNode = document.createElement('strong');
var vandNode = document.createElement('strong');
var normLink = Twinkle.fluff.linkBuilder.buildLink('SteelBlue', '回退');
var vandLink = Twinkle.fluff.linkBuilder.buildLink('Red', conv({ hans: '破坏', hant: '破壞' }));
$(normLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('norm', vandal, rev, page);
Twinkle.fluff.disableLinks(revNode);
});
$(vandLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('vand', vandal, rev, page);
Twinkle.fluff.disableLinks(revNode);
});
vandNode.appendChild(vandLink);
normNode.appendChild(normLink);
var separator = inline ? ' ' : ' || ';
if (!inline) {
var agfNode = document.createElement('strong');
var agfLink = Twinkle.fluff.linkBuilder.buildLink('DarkOliveGreen', '回退(AGF)');
$(agfLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('agf', vandal, rev, page);
// Twinkle.fluff.disableLinks(revNode); // rollbackInPlace not relevant for any inline situations
});
agfNode.appendChild(agfLink);
revNode.appendChild(agfNode);
}
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(normNode);
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(vandNode);
return revNode;
},
// Build [restore this revision] links
restoreThisRevisionLink: function(revisionRef, inline) {
// If not a specific revision number, should be wgDiffNewId/wgDiffOldId/wgRevisionId
revisionRef = typeof revisionRef === 'number' ? revisionRef : mw.config.get(revisionRef);
var elem = inline ? 'span' : 'div';
var revertToRevisionNode = document.createElement(elem);
revertToRevisionNode.setAttribute('id', 'tw-revert-to-' + revisionRef);
revertToRevisionNode.style.fontWeight = 'bold';
var revertToRevisionLink = Twinkle.fluff.linkBuilder.buildLink('SaddleBrown', conv({ hans: '恢复此版本', hant: '恢復此版本' }));
$(revertToRevisionLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revertToRevision(revisionRef);
});
if (inline) {
revertToRevisionNode.appendChild(document.createTextNode(' '));
}
revertToRevisionNode.appendChild(revertToRevisionLink);
return revertToRevisionNode;
}
};
Twinkle.fluff.addLinks = {
contributions: function() {
// $('sp-contributions-footer-anon-range') relies on the fmbox
// id in [[MediaWiki:Sp-contributions-footer-anon-range]] and
// is used to show rollback/vandalism links for IP ranges
var isRange = !!$('#sp-contributions-footer-anon-range')[0];
if (mw.config.exists('wgRelevantUserName') || isRange) {
// Get the username these contributions are for
var username = mw.config.get('wgRelevantUserName');
if (Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 ||
(mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1) ||
(mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1)) {
var $list = $('#mw-content-text').find('ul li:has(span.mw-uctop):has(.mw-changeslist-diff)');
$list.each(function(key, current) {
// revid is also available in the href of both
// .mw-changeslist-date or .mw-changeslist-diff
var page = $(current).find('.mw-contributions-title').text();
// Get username for IP ranges (wgRelevantUserName is null)
if (isRange) {
// The :not is possibly unnecessary, as it appears that
// .mw-userlink is simply not present if the username is hidden
username = $(current).find('.mw-userlink:not(.history-deleted)').text();
}
// It's unlikely, but we can't easily check for revdel'd usernames
// since only a strong element is provided, with no easy selector [[phab:T255903]]
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(username, true, current.dataset.mwRevid, page));
});
}
}
},
recentchanges: function() {
if (
(mw.config.get('wgCanonicalSpecialPageName') === 'Recentchanges' && Twinkle.getPref('showRollbackLinks').indexOf('recentchanges') !== -1)
|| (mw.config.get('wgCanonicalSpecialPageName') === 'Recentchangeslinked' && Twinkle.getPref('showRollbackLinks').indexOf('recentchangeslinked') !== -1)
) {
// Latest and revertable (not page creations, logs, categorizations, etc.)
var $list = $('.mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit');
// Exclude top-level header if "group changes" preference is used
// and find only individual lines or nested lines
$list = $list.not('.mw-rcfilters-ui-highlights-enhanced-toplevel').find('.mw-changeslist-line-inner, td.mw-enhanced-rc-nested');
$list.each(function(key, current) {
// The :not is possibly unnecessary, as it appears that
// .mw-userlink is simply not present if the username is hidden
var vandal = $(current).find('.mw-userlink:not(.history-deleted)').text();
var href = $(current).find('.mw-changeslist-diff').attr('href');
var rev = mw.util.getParamValue('diff', href);
var page = current.dataset.targetPage;
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(vandal, true, rev, page));
});
}
},
history: function() {
if (Twinkle.getPref('showRollbackLinks').indexOf('history') !== -1) {
// All revs
var histList = $('#pagehistory li').toArray();
// On first page of results, so add revert/rollback
// links to the top revision
if (!$('a.mw-firstlink').length) {
var first = histList.shift();
var vandal = $(first).find('.mw-userlink:not(.history-deleted)').text();
// Check for first username different than the top user,
// only apply rollback links if/when found
// for faster than every
for (var i = 0; i < histList.length; i++) {
if ($(histList[i]).find('.mw-userlink').text() !== vandal) {
first.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(vandal, true));
break;
}
}
}
// oldid
histList.forEach(function(rev) {
// From restoreThisRevision, non-transferable
// If the text has been revdel'd, it gets wrapped in a span with .history-deleted,
// and href will be undefined (and thus oldid is NaN)
var href = rev.querySelector('.mw-changeslist-date').href;
var oldid = parseInt(mw.util.getParamValue('oldid', href), 10);
if (!isNaN(oldid)) {
rev.appendChild(Twinkle.fluff.linkBuilder.restoreThisRevisionLink(oldid, true));
}
});
}
},
diff: function() {
// Autofill user talk links on diffs with vanarticle for easy warning, but don't autowarn
var warnFromTalk = function(xtitle) {
var talkLink = $('#mw-diff-' + xtitle + '2 .mw-usertoollinks a').first();
if (talkLink.length) {
var extraParams = 'vanarticle=' + mw.util.rawurlencode(Morebits.pageNameNorm) + '&' + 'noautowarn=true';
// diffIDs for vanarticlerevid
extraParams += '&vanarticlerevid=';
extraParams += xtitle === 'otitle' ? mw.config.get('wgDiffOldId') : mw.config.get('wgDiffNewId');
var href = talkLink.attr('href');
if (href.indexOf('?') === -1) {
talkLink.attr('href', href + '?' + extraParams);
} else {
talkLink.attr('href', href + '&' + extraParams);
}
}
};
// Older revision
warnFromTalk('otitle'); // Add quick-warn link to user talk link
// Don't load if there's a single revision or weird diff (cur on latest)
if (mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId'))) {
// Add a [restore this revision] link to the older revision
var oldTitle = document.getElementById('mw-diff-otitle1').parentNode;
var revertToRevision = Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffOldId');
oldTitle.insertBefore(revertToRevision, oldTitle.firstChild);
if (Twinkle.getPref('customRevertSummary').length > 0) {
revertToRevision.appendChild(document.createTextNode(' || '));
var revertsummary = new Morebits.quickForm.element({ type: 'select', name: 'revertsummary' });
revertsummary.append({
type: 'option',
label: conv({ hans: '选择回退理由', hant: '選擇回退理由' }),
value: ''
});
$(Twinkle.getPref('customRevertSummary')).each(function(_, e) {
revertsummary.append({
type: 'option',
label: e.label,
value: e.value
});
});
revertToRevision.appendChild(revertsummary.render().childNodes[0]);
}
}
// Newer revision
warnFromTalk('ntitle'); // Add quick-warn link to user talk link
// Add either restore or rollback links to the newer revision
// Don't show if there's a single revision or weird diff (prev on first)
if (document.getElementById('differences-nextlink')) {
// Not latest revision, add [restore this revision] link to newer revision
var newTitle = document.getElementById('mw-diff-ntitle1').parentNode;
newTitle.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffNewId'), newTitle.firstChild);
} else if (Twinkle.getPref('showRollbackLinks').indexOf('diff') !== -1 && mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId') || document.getElementById('differences-prevlink'))) {
// Normally .mw-userlink is a link, but if the
// username is hidden, it will be a span with
// .history-deleted as well. When a sysop views the
// hidden content, the span contains the username in a
// link element, which will *just* have
// .mw-userlink. The below thus finds the first
// instance of the class, which if hidden is the span
// and thus text returns undefined. Technically, this
// is a place where sysops *could* have more
// information available to them (as above, via
// &unhide=1), since the username will be available by
// checking a.mw-userlink instead, but revert() will
// need reworking around userHidden
var vandal = $('#mw-diff-ntitle2').find('.mw-userlink')[0].text;
var ntitle = document.getElementById('mw-diff-ntitle1').parentNode;
ntitle.insertBefore(Twinkle.fluff.linkBuilder.rollbackLinks(vandal), ntitle.firstChild);
}
},
oldid: function() { // Add a [restore this revision] link on old revisions
var title = document.getElementById('mw-revision-info').parentNode;
title.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgRevisionId'), title.firstChild);
}
};
Twinkle.fluff.disableLinks = function disablelinks(parentNode) {
// Array.from not available in IE11 :(
$(parentNode).children().each(function(_ix, node) {
node.innerHTML = node.textContent; // Feels like cheating
$(node).css('font-weight', 'normal').css('color', 'darkgray');
});
};
Twinkle.fluff.revert = function revertPage(type, vandal, rev, page) {
if (mw.util.isIPv6Address(vandal)) {
vandal = Morebits.sanitizeIPv6(vandal);
}
var pagename = page || mw.config.get('wgPageName');
var revid = rev || mw.config.get('wgCurRevisionId');
var summary = '';
if (document.getElementsByName('revertsummary')[0] !== undefined) {
summary = document.getElementsByName('revertsummary')[0].value;
}
if (Twinkle.fluff.rollbackInPlace) {
var notifyStatus = document.createElement('span');
mw.notify(notifyStatus, {
autoHide: false,
title: '回退' + page,
tag: 'twinklefluff_' + rev // Shouldn't be necessary given disableLink
});
Morebits.status.init(notifyStatus);
} else {
Morebits.status.init(document.getElementById('mw-content-text'));
$('#catlinks').remove();
}
var params = {
type: type,
user: vandal,
userHidden: !vandal, // Keep track of whether the username was hidden
pagename: pagename,
revid: revid,
summary: summary
};
var query = {
action: 'query',
prop: ['info', 'revisions'],
titles: pagename,
intestactions: 'edit',
rvlimit: Twinkle.getPref('revertMaxRevisions'),
rvprop: [ 'ids', 'timestamp', 'user' ],
curtimestamp: '',
meta: 'tokens',
type: 'csrf'
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取较早修订版本信息', hant: '抓取較早修訂版本資訊' }), query, Twinkle.fluff.callbacks.main);
wikipedia_api.params = params;
wikipedia_api.post();
};
Twinkle.fluff.revertToRevision = function revertToRevision(oldrev) {
var summary = '';
if (document.getElementsByName('revertsummary')[0] !== undefined) {
summary = document.getElementsByName('revertsummary')[0].value;
}
Morebits.status.init(document.getElementById('mw-content-text'));
var query = {
action: 'query',
prop: ['info', 'revisions'],
titles: mw.config.get('wgPageName'),
rvlimit: 1,
rvstartid: oldrev,
rvprop: [ 'ids', 'user' ],
format: 'xml',
curtimestamp: '',
meta: 'tokens',
type: 'csrf'
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取较早修订版本信息', hant: '抓取較早修訂版本資訊' }), query, Twinkle.fluff.callbacks.toRevision);
wikipedia_api.params = { rev: oldrev, summary: summary };
wikipedia_api.post();
};
Twinkle.fluff.callbacks = {
toRevision: function(apiobj) {
var xmlDoc = apiobj.responseXML;
var lastrevid = parseInt($(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var loadtimestamp = $(xmlDoc).find('api').attr('curtimestamp');
var csrftoken = $(xmlDoc).find('tokens').attr('csrftoken');
var revertToRevID = parseInt($(xmlDoc).find('rev').attr('revid'), 10);
var revertToUser = $(xmlDoc).find('rev').attr('user');
var revertToUserHidden = typeof $(xmlDoc).find('rev').attr('userhidden') === 'string';
if (revertToRevID !== apiobj.params.rev) {
apiobj.statelem.error(conv({ hans: '抓取到的修订版本与请求的修订版本不符,取消。', hant: '抓取到的修訂版本與請求的修訂版本不符,取消。' }));
return;
}
var optional_summary = prompt(conv({ hans: '请输入回退理由:', hant: '請輸入回退理由:' }) + ' ', apiobj.params.summary); // padded out to widen prompt in Firefox
if (optional_summary === null) {
apiobj.statelem.error(conv({ hans: '由用户取消。', hant: '由使用者取消。' }));
return;
}
var summary = Twinkle.fluff.formatSummary(conv({ hans: '回退到由$USER做出的修订版本', hant: '回退到由$USER做出的修訂版本' }) + revertToRevID,
revertToUserHidden ? null : revertToUser, optional_summary);
var query = {
action: 'edit',
title: mw.config.get('wgPageName'),
summary: summary,
tags: Twinkle.changeTags,
token: csrftoken,
undo: lastrevid,
undoafter: revertToRevID,
basetimestamp: touched,
starttimestamp: loadtimestamp,
minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf('torev') !== -1 ? true : undefined,
bot: true
};
// Handle watching, possible expiry
if (Twinkle.getPref('watchRevertedPages').indexOf('torev') !== -1) {
var watchOrExpiry = Twinkle.getPref('watchRevertedExpiry');
if (!watchOrExpiry || watchOrExpiry === 'no') {
query.watchlist = 'nochange';
} else if (watchOrExpiry === 'default' || watchOrExpiry === 'preferences') {
query.watchlist = 'preferences';
} else {
query.watchlist = 'watch';
// number allowed but not used in Twinkle.config.watchlistEnums
if (typeof watchOrExpiry === 'string' && watchOrExpiry !== 'yes') {
query.watchlistexpiry = watchOrExpiry;
}
}
}
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = '回退完成';
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '保存回退内容', hant: '儲存回退內容' }), query, Twinkle.fluff.callbacks.complete, apiobj.statelem);
wikipedia_api.params = apiobj.params;
wikipedia_api.post();
},
main: function(apiobj) {
var xmlDoc = apiobj.responseXML;
if (typeof $(xmlDoc).find('actions').attr('edit') === 'undefined') {
apiobj.statelem.error("Unable to edit the page, it's probably protected.");
return;
}
var lastrevid = parseInt($(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var loadtimestamp = $(xmlDoc).find('api').attr('curtimestamp');
var csrftoken = $(xmlDoc).find('tokens').attr('csrftoken');
var revs = $(xmlDoc).find('rev');
var statelem = apiobj.statelem;
var params = apiobj.params;
if (revs.length < 1) {
statelem.error(conv({ hans: '没有其它修订版本,无法回退', hant: '沒有其它修訂版本,無法回退' }));
return;
}
var top = revs[0];
var lastuser = top.getAttribute('user');
if (lastrevid < params.revid) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), [conv({ hans: '从服务器获取的最新修订版本ID ', hant: '從伺服器取得的最新修訂版本ID ' }), Morebits.htmlNode('strong', lastrevid), conv({ hans: ' 小于目前所显示的修订版本ID。这可能意味着当前修订版本已被删除、服务器延迟、或抓取到了坏掉的信息。取消。', hant: ' 小於目前所顯示的修訂版本ID。這可能意味著當前修訂版本已被刪除、伺服器延遲、或擷取到了壞掉的資訊。取消。' })]);
return;
}
// Used for user-facing alerts, messages, etc., not edits or summaries
var userNorm = params.user || Twinkle.fluff.hiddenName;
var index = 1;
if (params.revid !== lastrevid) {
Morebits.status.warn('警告', [conv({ hans: '最新修订版本 ', hant: '最新修訂版本 ' }), Morebits.htmlNode('strong', lastrevid), conv({ hans: ' 与我们的修订版本 ', hant: ' 與我們的修訂版本 ' }), Morebits.htmlNode('strong', params.revid), conv({ hans: '不同', hant: ' 不同' })]);
if (lastuser === params.user) {
switch (params.type) {
case 'vand':
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,因我们假定破坏,继续回退操作。', hant: ' 做出,因我們假定破壞,繼續回退操作。' })]);
break;
case 'agf':
Morebits.status.warn('警告', [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,因我们假定善意,取消回退操作,因为问题可能已被修复。', hant: ' 做出,因我們假定善意,取消回退操作,因為問題可能已被修復。' })]);
return;
default:
Morebits.status.warn('提示', [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,但我们还是不回退了。', hant: ' 做出,但我們還是不回退了。' })]);
return;
}
} else if (params.type === 'vand' &&
// Okay to test on user since it will either fail or sysop will correctly access it
// Besides, none of the trusted bots are going to be revdel'd
Twinkle.fluff.trustedBots.indexOf(top.getAttribute('user')) !== -1 && revs.length > 1 &&
revs[1].getAttribute('revid') === params.revid) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', lastuser), conv({ hans: ',一个可信的机器人做出,但之前的版本被认为是破坏,继续回退操作。', hant: ',一個可信的機器人做出,但之前的版本被認為是破壞,繼續回退操作。' })]);
index = 2;
} else {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', lastuser), conv({ hans: ' 做出,所以这个修订版本可能已经被回退了,取消回退操作。', hant: ' 做出,所以這個修訂版本可能已經被回退了,取消回退操作。' })]);
return;
}
} else {
// Expected revision is the same, so the users must match;
// this allows sysops to know whether the users are the same
params.user = lastuser;
userNorm = params.user || Twinkle.fluff.hiddenName;
}
if (Twinkle.fluff.trustedBots.indexOf(params.user) !== -1) {
switch (params.type) {
case 'vand':
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行破坏回退,这是一个可信的机器人,我们假定您要回退前一个修订版本。', hant: ' 執行破壞回退,這是一個可信的機器人,我們假定您要回退前一個修訂版本。' })]);
index = 2;
params.user = revs[1].getAttribute('user');
params.userHidden = revs[1].getAttribute('userhidden') === '';
break;
case 'agf':
Morebits.status.warn('提示', [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行善意回退,但这是一个可信的机器人,取消回退操作。', hant: ' 執行善意回退,但這是一個可信的機器人,取消回退操作。' })]);
return;
case 'norm':
/* falls through */
default:
var cont = confirm(conv({ hans: '选择了常规回退,但最新修改是由一个可信的机器人(', hant: '選擇了常規回退,但最新修改是由一個可信的機器人(' }) + userNorm + conv({ hans: ')做出的。确定以回退前一个修订版本,取消以回退机器人的修改', hant: ')做出的。確定以回退前一個修訂版本,取消以回退機器人的修改' }));
if (cont) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行常规回退,这是一个可信的机器人,基于确认,我们将回退前一个修订版本。', hant: ' 執行常規回退,這是一個可信的機器人,基於確認,我們將回退前一個修訂版本。' })]);
index = 2;
params.user = revs[1].getAttribute('user');
params.userHidden = revs[1].getAttribute('userhidden') === '';
userNorm = params.user || Twinkle.fluff.hiddenName;
} else {
Morebits.status.warn('提示', [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行常规回退,这是一个可信的机器人,基于确认,我们仍将回退这个修订版本。', hant: ' 執行常規回退,這是一個可信的機器人,基於確認,我們仍將回退這個修訂版本。' })]);
}
break;
}
}
var found = false;
var count = 0;
for (var i = index; i < revs.length; ++i) {
++count;
if (revs[i].getAttribute('user') !== params.user) {
found = i;
break;
}
}
if (!found) {
statelem.error([conv({ hans: '未找到之前的修订版本,可能 ', hant: '未找到之前的修訂版本,可能 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 是唯一贡献者,或这个用户连续做出了超过 ', hant: ' 是唯一貢獻者,或這個用戶連續做出了超過 ' }) + mw.language.convertNumber(Twinkle.getPref('revertMaxRevisions')) + conv({ hans: ' 次编辑。', hant: ' 次編輯。' })]);
return;
}
if (!count) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '我们将要回退0个修订版本,这没有意义,所以取消回退操作。可能是因为这个修订版本已经被回退,但修订版本ID仍是一样的。', hant: '我們將要回退0個修訂版本,這沒有意義,所以取消回退操作。可能是因為這個修訂版本已經被回退,但修訂版本ID仍是一樣的。' }));
return;
}
var good_revision = revs[found];
var userHasAlreadyConfirmedAction = false;
if (params.type !== 'vand' && count > 1) {
if (!confirm(userNorm + conv({ hans: ' 连续做出了 ', hant: ' 連續做出了 ' }) + mw.language.convertNumber(count) + conv({ hans: ' 次编辑,是否要全部回退?', hant: ' 次編輯,是否要全部回退?' }))) {
Morebits.status.info('提示', conv({ hans: '用户取消操作', hant: '使用者取消操作' }));
return;
}
userHasAlreadyConfirmedAction = true;
}
params.count = count;
params.goodid = good_revision.getAttribute('revid');
params.gooduser = good_revision.getAttribute('user');
params.gooduserHidden = good_revision.getAttribute('userhidden') === '';
statelem.status([Morebits.htmlNode('strong', mw.language.convertNumber(count)), conv({ hans: ' 个修订版本之前由 ', hant: ' 個修訂版本之前由 ' }), Morebits.htmlNode('strong', params.gooduserHidden ? Twinkle.fluff.hiddenName : params.gooduser), conv({ hans: ' 做出的修订版本 ', hant: ' 做出的修訂版本 ' }), Morebits.htmlNode('strong', params.goodid)]);
var summary, extra_summary;
switch (params.type) {
case 'agf':
extra_summary = prompt(conv({ hans: '可选的编辑摘要:', hant: '可選的編輯摘要:' }) + ' ', params.summary); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
userHasAlreadyConfirmedAction = true;
summary = Twinkle.fluff.formatSummary(conv({ hans: '回退$USER做出的出于[[WP:AGF|善意]]的编辑', hant: '回退$USER做出的出於[[WP:AGF|善意]]的編輯' }),
params.userHidden ? null : params.user, extra_summary);
break;
case 'vand':
summary = Twinkle.fluff.formatSummary('回退$USER做出的' + params.count + conv({ hans: '次编辑,到由', hant: '次編輯,到由' }) +
(params.gooduserHidden ? Twinkle.fluff.hiddenName : params.gooduser) + conv({ hans: '做出的最后修订版本 ', hant: '做出的最後修訂版本 ' }), params.userHidden ? null : params.user);
break;
case 'norm':
/* falls through */
default:
if (Twinkle.getPref('offerReasonOnNormalRevert')) {
extra_summary = prompt(conv({ hans: '可选的编辑摘要:', hant: '可選的編輯摘要:' }) + ' ', params.summary); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
userHasAlreadyConfirmedAction = true;
}
summary = Twinkle.fluff.formatSummary('回退$USER做出的' + params.count + conv({ hans: '次编辑', hant: '次編輯' }),
params.userHidden ? null : params.user, extra_summary);
break;
}
if ((Twinkle.getPref('confirmOnFluff') ||
// Mobile user agent taken from [[en:MediaWiki:Gadget-confirmationRollback-mobile.js]]
(Twinkle.getPref('confirmOnMobileFluff') && /Android|webOS|iPhone|iPad|iPod|BlackBerry|Mobile|Opera Mini/i.test(navigator.userAgent))) &&
!userHasAlreadyConfirmedAction && !confirm(conv({ hans: '回退页面:您确定吗?', hant: '回退頁面:您確定嗎?' }))) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
// Decide whether to notify the user on success
if (!Twinkle.fluff.skipTalk && Twinkle.getPref('openTalkPage').indexOf(params.type) !== -1 &&
!params.userHidden && mw.config.get('wgUserName') !== params.user) {
params.notifyUser = true;
// Pass along to the warn module
params.vantimestamp = top.getAttribute('timestamp');
}
var query = {
action: 'edit',
title: params.pagename,
summary: summary,
tags: Twinkle.changeTags,
token: csrftoken,
undo: lastrevid,
undoafter: params.goodid,
basetimestamp: touched,
starttimestamp: loadtimestamp,
minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf(params.type) !== -1 ? true : undefined,
bot: true
};
// Handle watching, possible expiry
if (Twinkle.getPref('watchRevertedPages').indexOf(params.type) !== -1) {
var watchOrExpiry = Twinkle.getPref('watchRevertedExpiry');
if (!watchOrExpiry || watchOrExpiry === 'no') {
query.watchlist = 'nochange';
} else if (watchOrExpiry === 'default' || watchOrExpiry === 'preferences') {
query.watchlist = 'preferences';
} else {
query.watchlist = 'watch';
// number allowed but not used in Twinkle.config.watchlistEnums
if (typeof watchOrExpiry === 'string' && watchOrExpiry !== 'yes') {
query.watchlistexpiry = watchOrExpiry;
}
}
}
if (!Twinkle.fluff.rollbackInPlace) {
Morebits.wiki.actionCompleted.redirect = params.pagename;
}
Morebits.wiki.actionCompleted.notice = '回退完成';
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '保存回退内容', hant: '儲存回退內容' }), query, Twinkle.fluff.callbacks.complete, statelem);
wikipedia_api.params = params;
wikipedia_api.post();
},
complete: function (apiobj) {
// TODO Most of this is copy-pasted from Morebits.wiki.page#fnSaveSuccess. Unify it
var xml = apiobj.getXML();
var $edit = $(xml).find('edit');
if ($(xml).find('captcha').length > 0) {
apiobj.statelem.error(conv({ hans: '不能回退,因维基服务器要求您输入验证码。', hant: '不能回退,因維基伺服器要求您輸入驗證碼。' }));
} else if ($edit.attr('nochange') === '') {
apiobj.statelem.error(conv({ hans: '要回退到的版本与当前版本相同,没什么要做的', hant: '要回退到的版本與目前版本相同,沒什麼要做的' }));
} else {
apiobj.statelem.info('完成');
var params = apiobj.params;
if (params.notifyUser && !params.userHidden) { // notifyUser only from main, not from toRevision
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '开启用户 ', hant: '開啟使用者 ' }), Morebits.htmlNode('strong', params.user), conv({ hans: ' 的讨论页', hant: ' 的討論頁' })]);
var windowQuery = {
title: 'User talk:' + params.user,
action: 'edit',
preview: 'yes',
vanarticle: params.pagename.replace(/_/g, ' '),
vanarticlerevid: params.revid,
vantimestamp: params.vantimestamp,
vanarticlegoodrevid: params.goodid,
type: params.type,
count: params.count
};
switch (Twinkle.getPref('userTalkPageMode')) {
case 'tab':
window.open(mw.util.getUrl('', windowQuery), '_blank');
break;
case 'blank':
window.open(mw.util.getUrl('', windowQuery), '_blank',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
case 'window':
/* falls through */
default:
window.open(mw.util.getUrl('', windowQuery),
window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
}
}
}
}
};
// If builtInString contains the string "$USER", it will be replaced
// by an appropriate user link if a user name is provided
Twinkle.fluff.formatSummary = function(builtInString, userName, customString) {
var result = builtInString;
// append user's custom reason
if (customString) {
result += ':' + Morebits.string.toUpperCaseFirstChar(customString);
}
// find number of UTF-8 bytes the resulting string takes up, and possibly add
// a contributions or contributions+talk link if it doesn't push the edit summary
// over the 499-byte limit
if (/\$USER/.test(builtInString)) {
if (userName) {
var resultLen = unescape(encodeURIComponent(result.replace('$USER', ''))).length;
var contribsLink = '[[Special:Contributions/' + userName + '|' + userName + ']]';
var contribsLen = unescape(encodeURIComponent(contribsLink)).length;
if (resultLen + contribsLen <= 499) {
var talkLink = '([[User talk:' + userName + conv({ hans: '|讨论]])', hant: '|討論]])' });
if (resultLen + contribsLen + unescape(encodeURIComponent(talkLink)).length <= 499) {
result = Morebits.string.safeReplace(result, '$USER', contribsLink + talkLink);
} else {
result = Morebits.string.safeReplace(result, '$USER', contribsLink);
}
} else {
result = Morebits.string.safeReplace(result, '$USER', userName);
}
} else {
result = Morebits.string.safeReplace(result, '$USER', Twinkle.fluff.hiddenName);
}
}
return result;
};
Twinkle.addInitCallback(Twinkle.fluff, 'fluff');
})(jQuery);
// </nowiki>
974e8421ae70d63b498f359538bce3bab0d2ed63
MediaWiki:Gadget-twinkleimage.js
8
159
320
2023-11-06T13:17:24Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) { // eslint-disable-line no-unused-vars
/*
****************************************
*** twinkleimage.js: Image CSD module
****************************************
* Mode of invocation: Tab ("DI")
* Active on: Local nonredirect file pages (not on Commons)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.image = function twinkleimage() {
if (mw.config.get('wgNamespaceNumber') === 6 &&
!document.getElementById('mw-sharedupload') &&
document.getElementById('mw-imagepage-section-filehistory')) {
Twinkle.addPortletLink(Twinkle.image.callback, conv({ hans: '图权', hant: '圖權' }), 'tw-di', conv({ hans: '提交文件快速删除', hant: '提交檔案快速刪除' }));
}
};
Twinkle.image.callback = function twinkleimageCallback() {
var Window = new Morebits.simpleWindow(600, 330);
Window.setTitle(conv({ hans: '文件快速删除候选', hant: '檔案快速刪除候選' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '快速删除方针', hant: '快速刪除方針' }), 'WP:CSD');
Window.addFooterLink(conv({ hans: '图权设置', hant: '圖權設定' }), 'WP:TW/PREF#image');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#image');
var form = new Morebits.quickForm(Twinkle.image.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '通知上传者', hant: '通知上傳者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '如果您在标记同一用户的很多文件,请取消此复选框以避免发送过多消息。CSD F6永远不会通知。', hant: '如果您在標記同一使用者的很多檔案,請取消此核取方塊以避免發送過多訊息。CSD F6永遠不會通知。' }),
checked: Twinkle.getPref('notifyUserOnDeli')
}
]
}
);
var field = form.append({
type: 'field',
label: conv({ hans: '需要的动作', hant: '需要的動作' })
});
field.append({
type: 'radio',
name: 'type',
list: [
{
label: conv({ hans: '来源不明(CSD F3)', hant: '來源不明(CSD F3)' }),
value: 'no source',
checked: true,
tooltip: conv({ hans: '本文件并未注明原始出处', hant: '本檔案並未註明原始出處' })
},
{
label: conv({ hans: '未知著作权或著作权无法被查证(CSD F4)', hant: '未知著作權或著作權無法被查證(CSD F4)' }),
value: 'no license',
tooltip: conv({ hans: '本文件缺少著作权信息,或声称的著作权信息无法被查证', hant: '本檔案缺少著作權資訊,或聲稱的著作權資訊無法被查證' })
},
{
label: conv({ hans: '来源不明(CSD F3)且未知著作权或著作权无法被查证(CSD F4)', hant: '來源不明(CSD F3)且未知著作權或著作權無法被查證(CSD F4)' }),
value: 'no source no license',
tooltip: conv({ hans: '本文件并未注明原始出处,且本文件缺少著作权信息或声称的著作权信息无法被查证', hant: '本檔案並未註明原始出處,且本檔案缺少著作權資訊或聲稱的著作權資訊無法被查證' })
},
{
label: conv({ hans: '没有被条目使用的非自由著作权文件(CSD F6)', hant: '沒有被條目使用的非自由著作權檔案(CSD F6)' }),
value: 'orphaned fair use',
tooltip: conv({ hans: '本文件为非自由著作权且没有被条目使用', hant: '本檔案為非自由著作權且沒有被條目使用' })
},
{
label: conv({ hans: '明显侵权之文件(CSD F8)', hant: '明顯侵權之檔案(CSD F8)' }),
value: 'no permission',
tooltip: conv({ hans: '上传者宣称拥有,而在其他来源找到的文件。或从侵权的来源获取的文件。', hant: '上傳者宣稱擁有,而在其他來源找到的檔案。或從侵權的來源取得的檔案。' }),
subgroup: {
name: 'f8_source',
type: 'textarea',
label: conv({ hans: '侵权来源:', hant: '侵權來源:' })
}
},
{
label: conv({ hans: '没有填写任何合理使用依据的非自由著作权文件(CSD F9)', hant: '沒有填寫任何合理使用依據的非自由著作權檔案(CSD F9)' }),
value: 'no fair use rationale',
tooltip: conv({ hans: '不适用于有争议但完整的合理使用依据。如果非自由著作权文件只有部分条目的使用依据,但同时被使用于未提供合理使用依据的条目,则本方针也不适用。', hant: '不適用於有爭議但完整的合理使用依據。如果非自由著作權檔案只有部分條目的使用依據,但同時被使用於未提供合理使用依據的條目,則本方針也不適用。' })
},
{
label: conv({ hans: '可被替代的非自由著作权文件(CSD F10)', hant: '可被替代的非自由著作權檔案(CSD F10)' }),
value: 'replaceable fair use',
tooltip: conv({ hans: '文件仅用于描述、识别或评论文件中展示的事物,或仅用作插图,且满足以下四个条件之一。如果给出了其他合理使用依据,不适用本条。如对文件的可替代性存在争议,应交文件存废讨论处理。本条也不适用于正在或曾经由文件存废讨论处理过的文件。', hant: '檔案僅用於描述、辨識或評論檔案中展示的事物,或僅用作插圖,且滿足以下四個條件之一。如果給出了其他合理使用依據,不適用本條。如對檔案的可替代性存在爭議,應交檔案存廢討論處理。本條也不適用於正在或曾經由檔案存廢討論處理過的檔案。' }),
subgroup: {
name: 'f10_type',
type: 'select',
label: conv({ hans: '适用类型:', hant: '適用類別:' }),
style: 'width: 85%;',
list: [
{ label: conv({ hans: '请选择', hant: '請選擇' }), value: '' },
{ label: conv({ hans: '有其他自由著作权文件展示相同的事物', hant: '有其他自由著作權檔案展示相同的事物' }), value: '1' },
{ label: conv({ hans: '文件描述的是在世或假定在世人物、仍然存在的建筑、室外雕塑或仍然在售的商品,且预计自行拍摄的照片不受他人著作权保护', hant: '檔案描述的是在世或假定在世人物、仍然存在的建築、室外雕塑或仍然在售的商品,且預計自行拍攝的相片不受他人著作權保護' }), value: '2' },
{ label: conv({ hans: '文件为可自行绘制的地图或图表', hant: '檔案為可自行繪製的地圖或圖表' }), value: '3' },
{ label: conv({ hans: '文件来自商业图片机构(如Getty)', hant: '檔案來自商業圖片機構(如Getty)' }), value: '4' }
]
}
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the parameters
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.type[0].dispatchEvent(evt);
};
Twinkle.image.callback.evaluate = function twinkleimageCallbackEvaluate(event) {
var type;
var notify = event.target.notify.checked;
var types = event.target.type;
for (var i = 0; i < types.length; ++i) {
if (types[i].checked) {
type = types[i].values;
break;
}
}
var csdcrit;
switch (type) {
case 'no source':
csdcrit = 'f3';
break;
case 'no license':
csdcrit = 'f4';
break;
case 'no source no license':
csdcrit = 'f3 f4';
break;
case 'orphaned fair use':
csdcrit = 'f6';
notify = false;
break;
case 'no permission':
csdcrit = 'f8';
break;
case 'no fair use rationale':
csdcrit = 'f9';
break;
case 'replaceable fair use':
csdcrit = 'f10';
break;
default:
throw new Error('Twinkle.image.callback.evaluate:未知条款');
}
var lognomination = Twinkle.getPref('logSpeedyNominations') && Twinkle.getPref('noLogOnSpeedyNomination').indexOf(csdcrit.toLowerCase()) === -1;
var templatename = type;
var params = {
type: type,
templatename: templatename,
normalized: csdcrit,
lognomination: lognomination
};
if (csdcrit === 'f8') {
params.f8_source = event.target['type.f8_source'].value;
}
if (csdcrit === 'f10') {
var f10_type = event.target['type.f10_type'].value;
if (!f10_type) {
alert(conv({ hans: 'CSD F10:请选择适用类型。', hant: 'CSD F10:請選擇適用類別。' }));
return false;
}
params.f10_type = f10_type;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(event.target);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
// Tagging image
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入删除标记', hant: '加入刪除標記' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.image.callbacks.taggingImage);
// Notifying uploader
if (notify) {
wikipedia_page.lookupCreation(Twinkle.image.callbacks.userNotification);
} else {
// add to CSD log if desired
if (lognomination) {
params.fromDI = true;
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
// No auto-notification, display what was going to be added.
if (type !== 'orphaned fair use') {
var noteData = document.createElement('pre');
noteData.appendChild(document.createTextNode('{{subst:Uploadvionotice|' + Morebits.pageNameNorm + '}}--~~~~'));
Morebits.status.info('提示', [conv({ hans: '这些内容应贴进上传者对话页:', hant: '這些內容應貼進上傳者討論頁:' }), document.createElement('br'), noteData]);
}
}
};
Twinkle.image.callbacks = {
taggingImage: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
// Adding discussion
if (params.type !== 'orphaned fair use') {
var wikipedia_page = new Morebits.wiki.page('Wikipedia:檔案存廢討論/快速刪除提報', conv({ hans: '加入快速删除记录项', hant: '加入快速刪除記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.image.callbacks.imageList);
}
var tag = '';
switch (params.type) {
case 'orphaned fair use':
tag = '{{subst:orphaned fair use}}\n';
break;
case 'no permission':
tag = '{{subst:' + params.templatename + '/auto|1=' + params.f8_source.replace(/http/g, 'http').replace(/\n+/g, '\n').replace(/^\s*([^*])/gm, '* $1').replace(/^\* $/m, '') + '}}\n';
break;
case 'replaceable fair use':
tag = '{{subst:' + params.templatename + '/auto|1=' + params.f10_type + '}}\n';
break;
default:
tag = '{{subst:' + params.templatename + '/auto}}\n';
break;
}
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|(?:hang|hold)[- ]?on)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && confirm(conv({ hans: '在页面上找到快速删除模板,要移除吗?', hant: '在頁面上找到快速刪除模板,要移除嗎?' }))) {
text = textNoSd;
}
pageobj.setPageText(tag + text);
var editSummary = conv({ hans: '请求快速删除(', hant: '請求快速刪除(' });
if (params.normalized === 'f3 f4') {
editSummary += '[[WP:CSD#F3|CSD F3]]+[[WP:CSD#F4|CSD F4]]';
} else {
editSummary += '[[WP:CSD#' + params.normalized.toUpperCase() + '|CSD ' + params.normalized.toUpperCase() + ']]';
}
editSummary += ')';
pageobj.setEditSummary(editSummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('deliWatchPage'));
pageobj.setCreateOption('nocreate');
pageobj.save();
},
userNotification: function(pageobj) {
var params = pageobj.getCallbackParameters();
var initialContrib = pageobj.getCreator();
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
pageobj.getStatusElement().warn('您(' + initialContrib + conv({ hans: ')创建了该页,跳过通知', hant: ')建立了該頁,跳過通知' }));
} else {
var talkPageName = 'User talk:' + initialContrib;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知上传者(', hant: '通知上傳者(' }) + initialContrib + ')');
flowpage.setTopic(conv({ hans: '文件[[', hant: '檔案[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的快速删除通知', hant: ']]的快速刪除通知' }));
flowpage.setContent('{{subst:Di-' + params.templatename + '-notice|1=' + Morebits.pageNameNorm + '}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知上传者(', hant: '通知上傳者(' }) + initialContrib + ')');
var notifytext = '\n{{subst:Di-' + params.templatename + '-notice|1=' + Morebits.pageNameNorm + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(conv({ hans: '通知:文件[[', hant: '通知:檔案[[' }) + Morebits.pageNameNorm + conv({ hans: ']]快速删除提名', hant: ']]快速刪除提名' }));
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('deliWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
params.fromDI = true;
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
},
imageList: function(pageobj) {
var text = pageobj.getPageText();
// var params = pageobj.getCallbackParameters();
pageobj.setPageText(text + '\n* [[:' + Morebits.pageNameNorm + ']]--~~~~');
pageobj.setEditSummary('加入[[' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.save();
}
};
Twinkle.addInitCallback(Twinkle.image, 'image');
})(jQuery);
// </nowiki>
7e0314e913de8c516941e1c946e4818e228f8a35
MediaWiki:Gadget-twinkleprotect.js
8
160
322
2023-11-06T13:17:27Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleprotect.js: Protect/RPP module
****************************************
* Mode of invocation: Tab ("PP"/"RPP")
* Active on: Non-special, non-MediaWiki pages
*/
// Note: a lot of code in this module is re-used/called by batchprotect.
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.protect = function twinkleprotect() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgNamespaceNumber') === 8) {
return;
}
// 如果是Flow讨论版而且是“Topic:”开头的帖子则不显示
if (mw.config.get('wgPageContentModel') === 'flow-board' && mw.config.get('wgPageName').indexOf('Topic:') === 0) {
return;
}
Twinkle.addPortletLink(Twinkle.protect.callback, conv({ hans: '保护', hant: '保護' }), 'tw-rpp',
Morebits.userIsSysop ? conv({ hans: '保护页面', hant: '保護頁面' }) : conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
};
Twinkle.protect.callback = function twinkleprotectCallback() {
var Window = new Morebits.simpleWindow(620, 530);
Window.setTitle(Morebits.userIsSysop ? conv({ hans: '施行或请求保护页面', hant: '施行或請求保護頁面' }) : conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '保护模板', hant: '保護模板' }), 'Template:Protection templates');
Window.addFooterLink(conv({ hans: '保护方针', hant: '保護方針' }), 'WP:PROT');
Window.addFooterLink(conv({ hans: '保护设置', hant: '保護設定' }), 'WP:TW/PREF#protect');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#protect');
var form = new Morebits.quickForm(Twinkle.protect.callback.evaluate);
var actionfield = form.append({
type: 'field',
label: conv({ hans: '操作类型', hant: '操作類別' })
});
if (Morebits.userIsSysop) {
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: conv({ hans: '保护页面', hant: '保護頁面' }),
value: 'protect',
checked: true
}
]
});
}
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: conv({ hans: '请求保护页面', hant: '請求保護頁面' }),
value: 'request',
tooltip: conv({ hans: '如果您想在WP:RFPP请求保护此页', hant: '如果您想在WP:RFPP請求保護此頁' }) + (Morebits.userIsSysop ? '而不是自行完成。' : '。'),
checked: !Morebits.userIsSysop
},
{
label: conv({ hans: '用保护模板标记此页', hant: '用保護模板標記此頁' }),
value: 'tag',
tooltip: conv({ hans: '可以用此为页面加上合适的保护模板。', hant: '可以用此為頁面加上合適的保護模板。' }),
disabled: mw.config.get('wgArticleId') === 0 || mw.config.get('wgPageContentModel') === 'Scribunto'
}
]
});
form.append({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
form.append({ type: 'field', label: '1', name: 'field1' });
form.append({ type: 'field', label: '2', name: 'field2' });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.actiontype[0].dispatchEvent(evt);
// get current protection level asynchronously
Twinkle.protect.fetchProtectionLevel();
};
// Customizable namespace and FlaggedRevs settings
// In theory it'd be nice to have restrictionlevels defined here,
// but those are only available via a siteinfo query
// Limit template editor; a Twinkle restriction, not a site setting
var isTemplate = mw.config.get('wgNamespaceNumber') === 10 || mw.config.get('wgNamespaceNumber') === 828;
// Contains the current protection level in an object
// Once filled, it will look something like:
// { edit: { level: "sysop", expiry: <some date>, cascade: true }, ... }
Twinkle.protect.currentProtectionLevels = {};
Twinkle.protect.previousProtectionLevels = {};
Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLevel() {
var api = new mw.Api();
var protectDeferred = api.get({
format: 'json',
indexpageids: true,
action: 'query',
list: 'logevents',
letype: 'protect',
letitle: mw.config.get('wgPageName'),
prop: 'info',
inprop: 'protection|watched',
titles: mw.config.get('wgPageName')
});
$.when.apply($, [protectDeferred]).done(function(protectData) {
var pageid = protectData.query.pageids[0];
var page = protectData.query.pages[pageid];
var current = {};
var previous = {};
// Save requested page's watched status for later in case needed when filing request
Twinkle.protect.watched = page.watchlistexpiry || page.watched === '';
$.each(page.protection, function(index, protection) {
if (protection.type !== 'aft') {
current[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
}
});
// Only use the log except unprotect
if (protectData.query.logevents.length >= 1 && protectData.query.logevents[0].action !== 'unprotect') {
Twinkle.protect.previousProtectionLog = protectData.query.logevents[0];
} else if (protectData.query.logevents.length >= 2) {
Twinkle.protect.previousProtectionLog = protectData.query.logevents[1];
}
if (Twinkle.protect.previousProtectionLog) {
$.each(Twinkle.protect.previousProtectionLog.params.details, function(index, protection) {
if (protection.type !== 'aft') {
previous[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
}
});
}
// show the protection level and log info
Twinkle.protect.hasProtectLog = !!protectData.query.logevents.length;
Twinkle.protect.currentProtectionLevels = current;
Twinkle.protect.previousProtectionLevels = previous;
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
});
};
Twinkle.protect.callback.showLogAndCurrentProtectInfo = function twinkleprotectCallbackShowLogAndCurrentProtectInfo() {
var currentlyProtected = !$.isEmptyObject(Twinkle.protect.currentProtectionLevels);
if (Twinkle.protect.hasProtectLog || Twinkle.protect.hasStableLog) {
var $linkMarkup = $('<span>');
if (Twinkle.protect.hasProtectLog) {
$linkMarkup.append(
$('<a target="_blank" href="' + mw.util.getUrl('Special:Log', { action: 'view', page: mw.config.get('wgPageName'), type: 'protect' }) + '">' + conv({ hans: '保护日志', hant: '保護日誌' }) + '</a>'),
Twinkle.protect.hasStableLog ? $('<span> • </span>') : null
);
}
Morebits.status.init($('div[name="hasprotectlog"] span')[0]);
Morebits.status.warn(
currentlyProtected
? conv({ hans: '先前保护', hant: '先前保護' })
: [
conv({ hans: '此页面曾在', hant: '此頁面曾在' }),
$('<b>' + new Morebits.date(Twinkle.protect.previousProtectionLog.timestamp).calendar('utc') + '</b>')[0],
'被' + Twinkle.protect.previousProtectionLog.user + conv({ hans: '保护', hant: '保護' }) + ':'
].concat(Twinkle.protect.formatProtectionDescription(Twinkle.protect.previousProtectionLevels)),
$linkMarkup[0]
);
}
Morebits.status.init($('div[name="currentprot"] span')[0]);
var protectionNode = [], statusLevel = 'info';
protectionNode = Twinkle.protect.formatProtectionDescription(Twinkle.protect.currentProtectionLevels);
if (currentlyProtected) {
statusLevel = 'warn';
}
Morebits.status[statusLevel](conv({ hans: '当前保护等级', hant: '目前保護等級' }), protectionNode);
};
Twinkle.protect.callback.changeAction = function twinkleprotectCallbackChangeAction(e) {
var field_preset;
var field1;
var field2;
switch (e.target.values) {
case 'protect':
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: conv({ hans: '选择默认:', hant: '選擇預設:' }),
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypesAdmin : Twinkle.protect.protectionTypesCreate
});
field2 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '保护选项', hant: '保護選項' }), name: 'field2' });
field2.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field2.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
// for existing pages
if (mw.config.get('wgArticleId')) {
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.editmodify,
list: [
{
label: conv({ hans: '修改编辑权限', hant: '修改編輯權限' }),
name: 'editmodify',
tooltip: conv({ hans: '如果此项关闭,编辑权限将不会修改。', hant: '如果此項關閉,編輯權限將不會修改。' }),
checked: true
}
]
});
field2.append({
type: 'select',
name: 'editlevel',
label: conv({ hans: '编辑权限:', hant: '編輯權限:' }),
event: Twinkle.protect.formevents.editlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE outside of templates and modules
return isTemplate || level.value !== 'templateeditor';
})
});
field2.append({
type: 'select',
name: 'editexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
$('input[name=small]', $(e.target).closest('form'))[0].checked = e.target.selectedIndex >= 4; // 1 month
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.movemodify,
list: [
{
label: conv({ hans: '修改移动权限', hant: '修改移動權限' }),
name: 'movemodify',
tooltip: conv({ hans: '如果此项被关闭,移动权限将不被修改。', hant: '如果此項被關閉,移動權限將不被修改。' }),
checked: true
}
]
});
field2.append({
type: 'select',
name: 'movelevel',
label: conv({ hans: '移动权限:', hant: '移動權限:' }),
event: Twinkle.protect.formevents.movelevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Autoconfirmed is required for a move, redundant
return level.value !== 'autoconfirmed' && (isTemplate || level.value !== 'templateeditor');
})
});
field2.append({
type: 'select',
name: 'moveexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
} else { // for non-existing pages
field2.append({
type: 'select',
name: 'createlevel',
label: conv({ hans: '创建权限:', hant: '建立權限:' }),
event: Twinkle.protect.formevents.createlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE always, and autoconfirmed in mainspace, redundant since WP:ACPERM
return level.value !== 'templateeditor';
})
});
field2.append({
type: 'select',
name: 'createexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (indefinite) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
}
field2.append({
type: 'checkbox',
list: [
{
name: 'close',
label: conv({ hans: '标记请求保护页面中的请求', hant: '標記請求保護頁面中的請求' }),
checked: true
}
]
});
field2.append({
type: 'textarea',
name: 'protectReason',
label: conv({ hans: '理由(保护日志):', hant: '理由(保護日誌):' })
});
if (!mw.config.get('wgArticleId') || mw.config.get('wgPageContentModel') === 'Scribunto') { // tagging isn't relevant for non-existing or module pages
break;
}
/* falls through */
case 'tag':
field1 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '标记选项', hant: '標記選項' }), name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'tagtype',
label: conv({ hans: '选择保护模板:', hant: '選擇保護模板:' }),
list: Twinkle.protect.protectionTags,
event: Twinkle.protect.formevents.tagtype
});
field1.append({
type: 'checkbox',
list: [
{
name: 'small',
label: conv({ hans: '使用图标(small=yes)', hant: '使用圖示(small=yes)' }),
tooltip: conv({ hans: '将给模板加上|small=yes参数,显示成右上角的一把挂锁。', hant: '將給模板加上|small=yes參數,顯示成右上角的一把掛鎖。' })
},
{
name: 'noinclude',
label: conv({ hans: '用<noinclude>包裹保护模板', hant: '用<noinclude>包裹保護模板' }),
tooltip: conv({ hans: '将保护模板包裹在<noinclude>中', hant: '將保護模板包裹在<noinclude>中' }),
checked: mw.config.get('wgNamespaceNumber') === 10
},
{
name: 'showexpiry',
label: conv({ hans: '在模板显示到期时间', hant: '在模板顯示到期時間' }),
tooltip: conv({ hans: '将给模板加上|expiry参数', hant: '將給模板加上|expiry參數' }),
checked: true,
hidden: e.target.values === 'tag'
}
]
});
break;
case 'request':
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '保护类型', hant: '保護類別' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: conv({ hans: '类型和理由:', hant: '類別和理由:' }),
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate
});
field1 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '选项', hant: '選項' }), name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'expiry',
label: conv({ hans: '时长:', hant: '時長:' }),
list: [
{ label: '', selected: true, value: '' },
{ label: conv({ hans: '临时', hant: '臨時' }), value: 'temporary' },
{ label: '永久', value: 'infinity' }
]
});
field1.append({
type: 'textarea',
name: 'reason',
label: '理由:'
});
break;
default:
alert(conv({ hans: '这玩意儿被逆袭的天邪鬼吃掉了!', hant: '這玩意兒被逆襲的天邪鬼吃掉了!' }));
break;
}
var oldfield;
if (field_preset) {
oldfield = $(e.target.form).find('fieldset[name="field_preset"]')[0];
oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field_preset"]').css('display', 'none');
}
if (field1) {
oldfield = $(e.target.form).find('fieldset[name="field1"]')[0];
oldfield.parentNode.replaceChild(field1.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field1"]').css('display', 'none');
}
if (field2) {
oldfield = $(e.target.form).find('fieldset[name="field2"]')[0];
oldfield.parentNode.replaceChild(field2.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field2"]').css('display', 'none');
}
if (e.target.values === 'protect') {
// fake a change event on the preset dropdown
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
e.target.form.category.dispatchEvent(evt);
// reduce vertical height of dialog
$(e.target.form).find('fieldset[name="field2"] select').parent().css({ display: 'inline-block', marginRight: '0.5em' });
}
// re-add protection level and log info, if it's available
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
};
// NOTE: This function is used by batchprotect as well
Twinkle.protect.formevents = {
editmodify: function twinkleprotectFormEditmodifyEvent(e) {
e.target.form.editlevel.disabled = !e.target.checked;
e.target.form.editexpiry.disabled = !e.target.checked || (e.target.form.editlevel.value === 'all');
e.target.form.editlevel.style.color = e.target.form.editexpiry.style.color = e.target.checked ? '' : 'transparent';
},
editlevel: function twinkleprotectFormEditlevelEvent(e) {
e.target.form.editexpiry.disabled = e.target.value === 'all';
},
movemodify: function twinkleprotectFormMovemodifyEvent(e) {
// sync move settings with edit settings if applicable
if (e.target.form.movelevel.disabled && !e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = e.target.form.editlevel.value;
e.target.form.moveexpiry.value = e.target.form.editexpiry.value;
} else if (e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = 'sysop';
e.target.form.moveexpiry.value = 'infinity';
}
e.target.form.movelevel.disabled = !e.target.checked;
e.target.form.moveexpiry.disabled = !e.target.checked || (e.target.form.movelevel.value === 'all');
e.target.form.movelevel.style.color = e.target.form.moveexpiry.style.color = e.target.checked ? '' : 'transparent';
},
movelevel: function twinkleprotectFormMovelevelEvent(e) {
e.target.form.moveexpiry.disabled = e.target.value === 'all';
},
createlevel: function twinkleprotectFormCreatelevelEvent(e) {
e.target.form.createexpiry.disabled = e.target.value === 'all';
},
tagtype: function twinkleprotectFormTagtypeEvent(e) {
e.target.form.small.disabled = e.target.form.noinclude.disabled = e.target.form.showexpiry.disabled = (e.target.value === 'none') || (e.target.value === 'noop');
}
};
Twinkle.protect.doCustomExpiry = function twinkleprotectDoCustomExpiry(target) {
var custom = prompt(conv({ hans: '输入自定义终止时间。\n您可以使用相对时间,如“1 minute”或“19 days”,或绝对时间“yyyymmddhhmm”(如“200602011405”是2006年02月01日14:05(UTC))', hant: '輸入自訂終止時間。\n您可以使用相對時間,如「1 minute」或「19 days」,或絕對時間「yyyymmddhhmm」(如「200602011405」是2006年02月01日14:05(UTC))' }), '');
if (custom) {
var option = document.createElement('option');
option.setAttribute('value', custom);
option.textContent = custom;
target.appendChild(option);
target.value = custom;
} else {
target.selectedIndex = 0;
}
};
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLevels = [
{ label: '全部', value: 'all' },
{ label: conv({ hans: '仅允许自动确认用户', hant: '僅允許自動確認使用者' }), value: 'autoconfirmed' },
{ label: conv({ hans: '仅允许延伸确认用户', hant: '僅允許延伸確認使用者' }), value: 'extendedconfirmed' },
{ label: conv({ hans: '仅模板编辑员和管理员', hant: '僅模板編輯員和管理員' }), value: 'templateeditor' },
{ label: conv({ hans: '仅管理员', hant: '僅管理員' }), value: 'sysop', selected: true }
];
// default expiry selection is conditionally set in Twinkle.protect.callback.changePreset
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLengths = [
{ label: '1天', value: '1 day' },
{ label: '3天', value: '3 days' },
{ label: conv({ hans: '1周', hant: '1週' }), value: '1 week' },
{ label: conv({ hans: '2周', hant: '2週' }), value: '2 weeks' },
{ label: conv({ hans: '1个月', hant: '1個月' }), value: '1 month' },
{ label: conv({ hans: '3个月', hant: '3個月' }), value: '3 months' },
{ label: conv({ hans: '6个月', hant: '6個月' }), value: '6 months' },
{ label: '1年', value: '1 year' },
{ label: conv({ hans: '无限期', hant: '無限期' }), value: 'infinity' },
{ label: conv({ hans: '自定义…', hant: '自訂…' }), value: 'custom' }
];
Twinkle.protect.protectionTypesAdmin = [
{ label: conv({ hans: '解除保护', hant: '解除保護' }), value: 'unprotect' },
{
label: conv({ hans: '全保护', hant: '全保護' }),
list: [
{ label: conv({ hans: '常规(全)', hant: '常規(全)' }), value: 'pp-protected' },
{ label: conv({ hans: '争议、编辑战(全)', hant: '爭議、編輯戰(全)' }), value: 'pp-dispute' }
]
},
{
label: conv({ hans: '模板保护', hant: '模板保護' }),
list: [
{ label: conv({ hans: '高风险模板(模板)', hant: '高風險模板(模板)' }), value: 'pp-template' }
]
},
{
label: conv({ hans: '延伸确认保护', hant: '延伸確認保護' }),
list: [
{ label: conv({ hans: '争议、编辑战(延伸)', hant: '爭議、編輯戰(延伸)' }), value: 'pp-extend-dispute' },
{ label: conv({ hans: '持续破坏(延伸)', hant: '持續破壞(延伸)' }), value: 'pp-vandalism' },
{ label: conv({ hans: '傀儡破坏(延伸)', hant: '傀儡破壞(延伸)' }), value: 'pp-sock' }
]
},
{
label: conv({ hans: '半保护', hant: '半保護' }),
list: [
{ label: conv({ hans: '常规(半)', hant: '常規(半)' }), value: 'pp-semi-protected' },
{ label: conv({ hans: '持续破坏(半)', hant: '持續破壞(半)' }), value: 'pp-semi-vandalism' },
{ label: conv({ hans: '违反生者传记方针(半)', hant: '違反生者傳記方針(半)' }), value: 'pp-semi-blp' },
{ label: conv({ hans: '傀儡破坏(半)', hant: '傀儡破壞(半)' }), value: 'pp-semi-sock' },
{ label: conv({ hans: '高风险模板(半)', hant: '高風險模板(半)' }), value: 'pp-semi-template' },
{ label: conv({ hans: '被封禁用户滥用讨论页(半)', hant: '被封禁使用者濫用討論頁(半)' }), value: 'pp-semi-usertalk' }
]
},
{
label: conv({ hans: '移动保护', hant: '移動保護' }),
list: [
{ label: conv({ hans: '常规(移动)', hant: '常規(移動)' }), value: 'pp-move' },
{ label: conv({ hans: '争议、移动战(移动)', hant: '爭議、移動戰(移動)' }), value: 'pp-move-dispute' },
{ label: conv({ hans: '移动破坏(移动)', hant: '移動破壞(移動)' }), value: 'pp-move-vandalism' },
{ label: conv({ hans: '高风险页面(移动)', hant: '高風險頁面(移動)' }), value: 'pp-move-indef' }
]
}
].filter(function(type) {
// Filter for templates
return isTemplate || (type.label !== '模板保护' && type.label !== '模板保護');
});
Twinkle.protect.protectionTypesCreateOnly = [
{
label: conv({ hans: '白纸保护', hant: '白紙保護' }),
list: [
{ label: conv({ hans: '常规(白纸)', hant: '常規(白紙)' }), value: 'pp-create' },
{ label: conv({ hans: '多次重复创建(白纸)', hant: '多次重複建立(白紙)' }), value: 'pp-create-repeat' },
{ label: conv({ hans: '持续破坏(白纸)', hant: '持續破壞(白紙)' }), value: 'pp-create-vandalism' },
{ label: conv({ hans: '已封禁用户的用户页(白纸)', hant: '已封禁使用者的使用者頁(白紙)' }), value: 'pp-create-userpage' }
]
}
];
Twinkle.protect.protectionTypes = Twinkle.protect.protectionTypesAdmin.concat(
Twinkle.protect.protectionTypesCreateOnly);
Twinkle.protect.protectionTypesCreate = [
{ label: conv({ hans: '解除保护', hant: '解除保護' }), value: 'unprotect' }
].concat(Twinkle.protect.protectionTypesCreateOnly);
// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
// Also note: stabilize = Pending Changes level
// expiry will override any defaults
Twinkle.protect.protectionPresetsInfo = {
'pp-protected': {
edit: 'sysop',
move: 'sysop',
reason: null
},
'pp-dispute': {
edit: 'sysop',
move: 'sysop',
reason: conv({ hans: '编辑战', hant: '編輯戰' })
},
'pp-template': {
edit: 'templateeditor',
move: 'templateeditor',
expiry: 'infinity',
reason: conv({ hans: '[[WP:HRT|高风险模板]]', hant: '[[WP:HRT|高風險模板]]' }),
template: 'noop'
},
'pp-vandalism': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '被自动确认用户破坏', hant: '被自動確認使用者破壞' })
},
'pp-extend-dispute': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '自动确认用户编辑战', hant: '自動確認使用者編輯戰' }),
template: 'pp-dispute'
},
'pp-sock': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '持续的傀儡破坏', hant: '持續的傀儡破壞' })
},
'pp-semi-vandalism': {
edit: 'autoconfirmed',
reason: conv({ hans: '被IP用户或新用户破坏', hant: '被IP使用者或新使用者破壞' }),
template: 'pp-vandalism'
},
'pp-semi-blp': {
edit: 'autoconfirmed',
reason: conv({ hans: 'IP用户或新用户违反生者传记方针', hant: 'IP使用者或新使用者違反生者傳記方針' })
},
'pp-semi-usertalk': {
edit: 'autoconfirmed',
reason: conv({ hans: '被封禁用户滥用其讨论页', hant: '被封禁使用者濫用其討論頁' })
},
'pp-semi-template': { // removed for now
edit: 'autoconfirmed',
expiry: 'infinity',
reason: conv({ hans: '[[WP:HRT|高风险模板]]', hant: '[[WP:HRT|高風險模板]]' }),
template: 'noop'
},
'pp-semi-sock': {
edit: 'autoconfirmed',
reason: conv({ hans: '持续的傀儡破坏', hant: '持續的傀儡破壞' }),
template: 'pp-sock'
},
'pp-semi-protected': {
edit: 'autoconfirmed',
reason: null,
template: 'pp-protected'
},
'pp-move': {
move: 'sysop',
reason: null
},
'pp-move-dispute': {
move: 'sysop',
reason: conv({ hans: '页面移动战', hant: '頁面移動戰' })
},
'pp-move-vandalism': {
move: 'sysop',
reason: conv({ hans: '移动破坏', hant: '移動破壞' })
},
'pp-move-indef': {
move: 'sysop',
expiry: 'infinity',
reason: conv({ hans: '高风险页面', hant: '高風險頁面' })
},
'unprotect': {
edit: 'all',
move: 'all',
create: 'all',
reason: null,
template: 'none'
},
'pp-create': {
create: 'autoconfirmed',
reason: null
},
'pp-create-repeat': {
create: 'autoconfirmed',
reason: conv({ hans: '多次重复创建', hant: '多次重複建立' })
},
'pp-create-vandalism': {
create: 'autoconfirmed',
reason: conv({ hans: '被IP用户或新用户破坏', hant: '被IP使用者或新使用者破壞' })
},
'pp-create-userpage': {
create: 'sysop',
expiry: 'infinity',
reason: conv({ hans: '被永久封禁的用户页', hant: '被永久封禁的使用者頁面' })
}
};
Twinkle.protect.protectionTags = [
{
label: conv({ hans: '无(移除现有模板)', hant: '無(移除現有模板)' }),
value: 'none'
},
{
label: conv({ hans: '无(不移除现有模板)', hant: '無(不移除現有模板)' }),
value: 'noop'
},
{
label: '通用模板',
list: [
{ label: '{{pp-dispute}}: ' + conv({ hans: '争议', hant: '爭議' }), value: 'pp-dispute' },
{ label: '{{pp-vandalism}}: ' + conv({ hans: '破坏', hant: '破壞' }), value: 'pp-vandalism', selected: true },
{ label: '{{pp-sock}}: ' + '傀儡', value: 'pp-sock' },
{ label: '{{pp-template}}: ' + conv({ hans: '高风险模板', hant: '高風險模板' }), value: 'pp-template' },
{ label: '{{pp-protected}}: ' + conv({ hans: '常规', hant: '常規' }), value: 'pp-protected' }
]
},
{
label: conv({ hans: '半保护模板', hant: '半保護模板' }),
list: [
{ label: '{{pp-semi-usertalk}}: ' + conv({ hans: '封禁的用户', hant: '封禁的使用者' }), value: 'pp-semi-usertalk' },
{ label: '{{pp-semi-blp}}: ' + conv({ hans: '生者传记', hant: '生者傳記' }), value: 'pp-semi-blp' },
{ label: '{{pp-semi-indef}}: ' + conv({ hans: '长期', hant: '長期' }), value: 'pp-semi-indef' }
]
},
{
label: conv({ hans: '移动保护模板', hant: '移動保護模板' }),
list: [
{ label: '{{pp-move-dispute}}: ' + conv({ hans: '争议', hant: '爭議' }), value: 'pp-move-dispute' },
{ label: '{{pp-move-vandalism}}: ' + conv({ hans: '破坏', hant: '破壞' }), value: 'pp-move-vandalism' },
{ label: '{{pp-move-indef}}: ' + conv({ hans: '长期', hant: '長期' }), value: 'pp-move-indef' },
{ label: '{{pp-move}}: ' + conv({ hans: '常规', hant: '常規' }), value: 'pp-move' }
]
}
];
Twinkle.protect.callback.changePreset = function twinkleprotectCallbackChangePreset(e) {
var form = e.target.form;
var actiontypes = form.actiontype;
var actiontype;
for (var i = 0; i < actiontypes.length; i++) {
if (!actiontypes[i].checked) {
continue;
}
actiontype = actiontypes[i].values;
break;
}
if (actiontype === 'protect') { // actually protecting the page
var item = Twinkle.protect.protectionPresetsInfo[form.category.value];
if (mw.config.get('wgArticleId')) {
if (item.edit) {
form.editmodify.checked = true;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
form.editlevel.value = item.edit;
Twinkle.protect.formevents.editlevel({ target: form.editlevel });
} else {
form.editmodify.checked = false;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
}
if (item.move) {
form.movemodify.checked = true;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
form.movelevel.value = item.move;
Twinkle.protect.formevents.movelevel({ target: form.movelevel });
} else {
form.movemodify.checked = false;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
}
form.editexpiry.value = form.moveexpiry.value = item.expiry || '1 week';
} else {
if (item.create) {
form.createlevel.value = item.create;
Twinkle.protect.formevents.createlevel({ target: form.createlevel });
form.createexpiry.value = item.createexpiry || '1 week';
}
form.createexpiry.value = item.expiry || '1 week';
}
var reasonField = actiontype === 'protect' ? form.protectReason : form.reason;
if (item.reason) {
reasonField.value = item.reason;
} else {
reasonField.value = '';
}
// sort out tagging options, disabled if nonexistent or lua
if (mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto') {
if (form.category.value === 'unprotect') {
form.tagtype.value = 'none';
} else {
form.tagtype.value = item.template ? item.template : form.category.value;
}
Twinkle.protect.formevents.tagtype({ target: form.tagtype });
if (/template/.test(form.category.value)) {
form.noinclude.checked = true;
} else if (mw.config.get('wgNamespaceNumber') !== 10) {
form.noinclude.checked = false;
}
}
} else { // RPP request
if (form.category.value === 'unprotect') {
form.expiry.value = '';
form.expiry.disabled = true;
} else {
form.expiry.value = '';
form.expiry.disabled = false;
}
}
};
Twinkle.protect.callback.evaluate = function twinkleprotectCallbackEvaluate(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
var tagparams;
if (input.actiontype === 'tag' || (input.actiontype === 'protect' && mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto')) {
tagparams = {
tag: input.tagtype,
reason: (input.tagtype === 'pp-protected' || input.tagtype === 'pp-semi-protected' || input.tagtype === 'pp-move') && input.protectReason ? input.protectReason : null,
showexpiry: input.actiontype === 'protect' ? input.showexpiry : null,
small: input.small,
noinclude: input.noinclude
};
if (input.actiontype === 'protect') {
if (input.editmodify) {
tagparams.expiry = input.editexpiry;
} else if (input.movemodify) {
tagparams.expiry = input.moveexpiry;
}
}
}
var closeparams = {};
if (input.close) {
if (input.category === 'unprotect') {
closeparams.type = 'unprotect';
} else if (mw.config.get('wgArticleId')) {
if (input.editmodify) {
if (input.editlevel === 'sysop') {
closeparams.type = 'full';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'templateeditor') {
closeparams.type = 'temp';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'extendedconfirmed') {
closeparams.type = 'ecp';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'autoconfirmed') {
closeparams.type = 'semi';
closeparams.expiry = input.editexpiry;
}
} else if (input.movemodify && ['sysop', 'templateeditor', 'extendedconfirmed'].indexOf(input.movelevel) !== -1) {
closeparams.type = 'move';
closeparams.expiry = input.moveexpiry;
}
} else {
if (input.createlevel !== 'all') {
closeparams.type = 'salt';
closeparams.expiry = input.createexpiry;
}
}
}
switch (input.actiontype) {
case 'protect':
// protect the page
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '保护完成', hant: '保護完成' });
var statusInited = false;
var thispage;
var allDone = function twinkleprotectCallbackAllDone() {
if (thispage) {
thispage.getStatusElement().info('完成');
}
if (tagparams) {
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
}
if (closeparams && closeparams.type) {
var rppPage = new Morebits.wiki.page('Wikipedia:请求保护页面', conv({ hans: '关闭请求', hant: '關閉請求' }));
rppPage.setFollowRedirect(true);
rppPage.setCallbackParameters(closeparams);
rppPage.load(Twinkle.protect.callbacks.closeRequest);
}
};
var protectIt = function twinkleprotectCallbackProtectIt(next) {
thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '保护页面', hant: '保護頁面' }));
var anyExtendProtection = false;
if (mw.config.get('wgArticleId')) {
if (input.editmodify) {
if (input.editlevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setEditProtection(input.editlevel, input.editexpiry);
}
if (input.movemodify) {
// Ensure a level has actually been chosen
if (input.movelevel) {
if (input.movelevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setMoveProtection(input.movelevel, input.moveexpiry);
} else {
alert(conv({ hans: '您需要选择保护层级!', hant: '您需要選擇保護層級!' }));
return;
}
}
thispage.setWatchlist(Twinkle.getPref('watchProtectedPages'));
} else {
if (input.createlevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setCreateProtection(input.createlevel, input.createexpiry);
thispage.setWatchlist(false);
}
if (input.protectReason) {
if (anyExtendProtection && !/(争议|爭議|编辑战|編輯戰|破坏|破壞|重复创建|重複建立)/.test(input.protectReason)
&& !confirm(conv({ hans: '根据保护方针,延伸确认保护仅可用于编辑战或破坏,但是您指定的保护理由似乎未符此条件。单击确认以继续保护,单击取消以更改保护设置', hant: '根據保護方針,延伸確認保護僅可用於編輯戰或破壞,但是您指定的保護理由似乎未符此條件。點擊確認以繼續保護,點擊取消以更改保護設定' }))) {
return;
}
thispage.setEditSummary(input.protectReason);
thispage.setChangeTags(Twinkle.changeTags);
} else {
alert(conv({ hans: '您必须输入保护理由,这将被记录在保护日志中。', hant: '您必須輸入保護理由,這將被記錄在保護日誌中。' }));
return;
}
if (!statusInited) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
statusInited = true;
}
thispage.setChangeTags(Twinkle.changeTags);
thispage.protect(next);
};
if (input.editmodify || input.movemodify || !mw.config.get('wgArticleId')) {
protectIt(allDone);
} else {
alert(conv({ hans: '请告诉Twinkle要做什么!\n如果您只是想标记该页,请选择上面的“用保护模板标记此页”选项。', hant: '請告訴Twinkle要做什麼!\n如果您只是想標記該頁,請選擇上面的「用保護模板標記此頁」選項。' }));
}
break;
case 'tag':
// apply a protection template
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.followRedirect = false;
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
break;
case 'request':
// file request at RFPP
var typename, typereason;
switch (input.category) {
case 'pp-dispute':
case 'pp-protected':
typename = conv({ hans: '全保护', hant: '全保護' });
break;
case 'pp-template':
typename = conv({ hans: '模板保护', hant: '模板保護' });
break;
case 'pp-vandalism':
case 'pp-extend-dispute':
typename = conv({ hans: '延伸确认保护', hant: '延伸確認保護' });
break;
case 'pp-semi-vandalism':
case 'pp-semi-usertalk':
case 'pp-semi-template': // removed for now
case 'pp-semi-sock':
case 'pp-semi-blp':
case 'pp-semi-protected':
typename = conv({ hans: '半保护', hant: '半保護' });
break;
case 'pp-move':
case 'pp-move-dispute':
case 'pp-move-indef':
case 'pp-move-vandalism':
typename = conv({ hans: '移动保护', hant: '移動保護' });
break;
case 'pp-create':
case 'pp-create-offensive':
case 'pp-create-blp':
case 'pp-create-salt':
case 'pp-create-userpage':
case 'pp-create-repeat':
case 'pp-create-vandalism':
typename = conv({ hans: '白纸保护', hant: '白紙保護' });
break;
case 'unprotect':
/* falls through */
default:
typename = conv({ hans: '解除保护', hant: '解除保護' });
break;
}
switch (input.category) {
case 'pp-dispute':
case 'pp-extend-dispute':
typereason = conv({ hans: '争议、编辑战', hant: '爭議、編輯戰' });
break;
case 'pp-vandalism':
case 'pp-semi-vandalism':
case 'pp-create-vandalism':
typereason = conv({ hans: '持续破坏', hant: '持續破壞' });
break;
case 'pp-template':
case 'pp-semi-template': // removed for now
typereason = conv({ hans: '高风险模板', hant: '高風險模板' });
break;
case 'pp-create-userpage':
typereason = conv({ hans: '被永久封禁的用户页', hant: '被永久封鎖的使用者頁面' });
break;
case 'pp-semi-usertalk':
typereason = conv({ hans: '已封禁用户的讨论页', hant: '已封鎖使用者的討論頁' });
break;
case 'pp-semi-sock':
typereason = conv({ hans: '傀儡破坏', hant: '傀儡破壞' });
break;
case 'pp-semi-blp':
typereason = conv({ hans: '违反生者传记方针', hant: '違反生者傳記方針' });
break;
case 'pp-move-dispute':
typereason = conv({ hans: '争议、移动战', hant: '爭議、移動戰' });
break;
case 'pp-move-vandalism':
typereason = conv({ hans: '移动破坏', hant: '移動破壞' });
break;
case 'pp-move-indef':
typereason = conv({ hans: '高风险页面', hant: '高風險頁面' });
break;
case 'pp-create-repeat':
typereason = conv({ hans: '多次重复创建', hant: '多次重複建立' });
break;
default:
typereason = '';
break;
}
var reason = typereason;
if (input.reason !== '') {
if (typereason !== '') {
reason += ':';
}
reason += input.reason;
}
if (reason !== '') {
reason = Morebits.string.appendPunctuation(reason);
}
var rppparams = {
reason: reason,
typename: typename,
category: input.category,
expiry: input.expiry
};
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var rppName = 'Wikipedia:请求保护页面';
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = rppName;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
var rppPage = new Morebits.wiki.page(rppName, conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
rppPage.setFollowRedirect(true);
rppPage.setCallbackParameters(rppparams);
rppPage.load(Twinkle.protect.callbacks.fileRequest);
break;
default:
alert('twinkleprotect: 未知操作类型');
break;
}
};
Twinkle.protect.callbacks = {
taggingPageInitial: function(tagparams) {
if (tagparams.tag === 'noop') {
Morebits.status.info(conv({ hans: '应用保护模板', hant: '應用保護模板' }), conv({ hans: '没什么要做的', hant: '沒什麼要做的' }));
return;
}
var pageName = mw.config.get('wgPageName');
Morebits.wiki.flow.check(pageName, function () {
var flowpage = new Morebits.wiki.flow(pageName, conv({ hans: '标记Flow页描述', hant: '標記Flow頁描述' }));
flowpage.setCallbackParameters(tagparams);
flowpage.viewHeader(Twinkle.protect.callbacks.taggingFlowPage);
}, function () {
var protectedPage = new Morebits.wiki.page(pageName, conv({ hans: '标记页面', hant: '標記頁面' }));
protectedPage.setCallbackParameters(tagparams);
protectedPage.load(Twinkle.protect.callbacks.taggingPage);
});
},
getTaggedPage: function(params, text) {
var tag, summary;
var oldtag_re = /(?:<noinclude>)?[ \t]*\{\{\s*(pp-[^{}]*?|protected|(?:t|v|s|p-|usertalk-v|usertalk-s|sb|move)protected(?:2)?|protected template|privacy protection)\s*?\}\}\s*(?:<\/noinclude>)?\s*/gi;
var re_result = oldtag_re.exec(text);
if (re_result) {
if (params.tag === 'none' || confirm(conv({ hans: '在页面上找到{{', hant: '在頁面上找到{{' }) + re_result[1] + conv({ hans: '}}\n单击确定以移除,或单击取消以取消操作。', hant: '}}\n點擊確定以移除,或點擊取消以取消操作。' }))) {
text = text.replace(oldtag_re, '');
}
}
if (params.tag === 'none') {
summary = conv({ hans: '移除保护模板', hant: '移除保護模板' });
} else {
tag = params.tag;
if (params.reason) {
tag += '|reason=' + params.reason;
}
if (params.showexpiry && params.expiry && !Morebits.string.isInfinity(params.expiry)) {
tag += '|expiry={{subst:#time:c|' + params.expiry + '}}';
}
if (params.small) {
tag += '|small=yes';
}
if (/^\s*#(?:redirect|重定向|重新導向)/i.test(text)) { // redirect page
// Only tag if no {{rcat shell}} is found
if (!text.match(/{{(?:Redirect[ _]category shell|Rcat[ _]shell|This[ _]is a redirect|多种类型重定向|多種類型重定向|多種類型重新導向|多种类型重新导向|R0|其他重定向|RCS|Redirect[ _]shell)/i)) {
text = text.replace(/#(?:redirect|重定向|重新導向) ?(\[\[.*?\]\])(.*)/i, '#REDIRECT $1$2\n\n{{' + tag + '}}');
} else {
Morebits.status.info('已存在Redirect category shell', conv({ hans: '没什么可做的', hant: '沒什麼可做的' }));
return;
}
} else {
if (params.noinclude) {
tag = '<noinclude>{{' + tag + '}}</noinclude>';
// 只有表格需要单独加回车,其他情况加回车会破坏模板。
if (text.indexOf('{|') === 0) {
tag += '\n';
}
} else {
tag = '{{' + tag + '}}\n';
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
summary = '加入{{' + params.tag + '}}';
}
return {
text: text,
summary: summary
};
},
taggingPage: function(protectedPage) {
var params = protectedPage.getCallbackParameters();
var text = protectedPage.getPageText();
var newVersion = Twinkle.protect.callbacks.getTaggedPage(params, text);
if (typeof newVersion === 'undefined') {
protectedPage.getStatusElement().info('完成');
return;
}
protectedPage.setEditSummary(newVersion.summary);
protectedPage.setChangeTags(Twinkle.changeTags);
protectedPage.setWatchlist(Twinkle.getPref('watchPPTaggedPages'));
protectedPage.setPageText(newVersion.text);
protectedPage.setCreateOption('nocreate');
protectedPage.suppressProtectWarning(); // no need to let admins know they are editing through protection
protectedPage.save();
},
taggingFlowPage: function(flowpage) {
var params = flowpage.getCallbackParameters();
var text = flowpage.getHeader();
var newVersion = Twinkle.protect.callbacks.getTaggedPage(params, text);
if (typeof newVersion === 'undefined') {
flowpage.getStatusElement().info('完成');
return;
}
flowpage.setHeader(newVersion.text);
flowpage.editHeader();
},
fileRequest: function(rppPage) {
var params = rppPage.getCallbackParameters();
var text = rppPage.getPageText();
var statusElement = rppPage.getStatusElement();
var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + Morebits.string.escapeRegExp(Morebits.pageNameNorm) + '\\s*(\\]\\])?\\s*===', 'm');
var tag = rppRe.exec(text);
var rppLink = document.createElement('a');
rppLink.setAttribute('href', mw.util.getUrl(rppPage.getPageName()));
rppLink.appendChild(document.createTextNode(rppPage.getPageName()));
if (tag) {
statusElement.error([rppLink, conv({ hans: '已有对此页面的保护提名,取消操作。', hant: '已有對此頁面的保護提名,取消操作。' })]);
return;
}
var newtag = '=== [[:' + Morebits.pageNameNorm + ']] ===' + '\n';
if (new RegExp('^' + mw.util.escapeRegExp(newtag).replace(/\s+/g, '\\s*'), 'm').test(text)) {
statusElement.error([rppLink, conv({ hans: '已有对此页面的保护提名,取消操作。', hant: '已有對此頁面的保護提名,取消操作。' })]);
return;
}
var words;
switch (params.expiry) {
case 'temporary':
words = conv({ hans: '临时', hant: '臨時' });
break;
case 'infinity':
words = '永久';
break;
default:
words = '';
break;
}
words += params.typename;
newtag += '* <small>' + conv({ hans: '当前保护状态', hant: '目前保護狀態' }) + ':{{protection status|' + (/=/.test(Morebits.pageNameNorm) ? '1=' : '') + Morebits.pageNameNorm + '}}</small>\n';
newtag += conv({ hans: '请求', hant: '請求' }) + Morebits.string.toUpperCaseFirstChar(words) + (params.reason !== '' ? ':' +
Morebits.string.formatReasonText(params.reason) : '。') + '--~~~~';
var reg;
if (params.category === 'unprotect') {
reg = /(==\s*请求解除保护\s*==)/;
} else {
reg = /({{\s*\/header\s*}})/;
}
var originalTextLength = text.length;
text = text.replace(reg, '$1\n' + newtag + '\n');
if (text.length === originalTextLength) {
var linknode = document.createElement('a');
linknode.setAttribute('href', mw.util.getUrl('Wikipedia:Twinkle/修复RFPP'));
linknode.appendChild(document.createTextNode(conv({ hans: '如何修复RFPP', hant: '如何修復RFPP' })));
statusElement.error([conv({ hans: '无法在WP:RFPP上找到相关定位点标记,要修复此问题,请参见', hant: '無法在WP:RFPP上找到相關定位點標記,要修復此問題,請參見' }), linknode, '。']);
return;
}
statusElement.status('加入新提名…');
rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ ' + conv({ hans: '请求对', hant: '請求對' }) + '[[' + Morebits.pageNameNorm + ']]' + params.typename);
rppPage.setChangeTags(Twinkle.changeTags);
rppPage.setPageText(text);
rppPage.setCreateOption('recreate');
rppPage.save(function() {
// Watch the page being requested
var watchPref = Twinkle.getPref('watchRequestedPages');
// action=watch has no way to rely on user preferences (T262912), so we do it manually.
// The watchdefault pref appears to reliably return '1' (string),
// but that's not consistent among prefs so might as well be "correct"
var watch = watchPref !== 'no' && (watchPref !== 'default' || !!parseInt(mw.user.options.get('watchdefault'), 10));
if (watch) {
var watch_query = {
action: 'watch',
titles: mw.config.get('wgPageName'),
token: mw.user.tokens.get('watchToken')
};
// Only add the expiry if page is unwatched or already temporarily watched
if (Twinkle.protect.watched !== true && watchPref !== 'default' && watchPref !== 'yes') {
watch_query.expiry = watchPref;
}
new Morebits.wiki.api(conv({ hans: '将请求保护的页面加入到监视列表', hant: '將請求保護的頁面加入到監視清單' }), watch_query).post();
}
});
},
closeRequest: function(rppPage) {
var params = rppPage.getCallbackParameters();
var text = rppPage.getPageText();
var statusElement = rppPage.getStatusElement();
var sections = text.split(/(?=\n==\s*请求解除保护\s*==)/);
if (sections.length !== 2) {
var linknode2 = document.createElement('a');
linknode2.setAttribute('href', mw.util.getUrl('Wikipedia:Twinkle/修复RFPP'));
linknode2.appendChild(document.createTextNode('如何修复RFPP'));
statusElement.error([conv({ hans: '无法在WP:RFPP上找到相关定位点标记,要修复此问题,请参见', hant: '無法在WP:RFPP上找到相關定位點標記,要修復此問題,請參見' }), linknode2, '。']);
return;
}
var sectionText, expiryText = '';
if (params.type === 'unprotect') {
sectionText = sections[1];
} else {
sectionText = sections[0];
expiryText = Morebits.string.formatTime(params.expiry);
}
var requestList = sectionText.split(/(?=\n===.+===\s*\n)/);
var found = false;
var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + Morebits.pageNameRegex(Morebits.pageNameNorm) + '\\s*(\\]\\])?\\s*===', 'm');
for (var i = 1; i < requestList.length; i++) {
if (rppRe.exec(requestList[i])) {
requestList[i] = requestList[i].trimRight();
if (params.type === 'unprotect') {
requestList[i] += '\n: {{RFPP|isun}}。--~~~~\n';
} else {
requestList[i] += '\n: {{RFPP|' + params.type + '|'
+ (Morebits.string.isInfinity(params.expiry) ? 'infinity' : expiryText)
+ '}}。--~~~~\n';
}
found = true;
break;
}
}
if (!found) {
statusElement.warn(conv({ hans: '没有找到相关的请求', hant: '沒有找到相關的請求' }));
return;
}
if (params.type === 'unprotect') {
text = sections[0] + requestList.join('');
} else {
text = requestList.join('') + sections[1];
}
var summary = '';
if (params.type === 'unprotect') {
sectionText = sections[1];
} else {
sectionText = sections[0];
}
switch (params.type) {
case 'semi':
summary = conv({ hans: '半保护', hant: '半保護' });
break;
case 'temp':
summary = conv({ hans: '模板保护', hant: '模板保護' });
break;
case 'ecp':
summary = conv({ hans: '延伸确认保护', hant: '延伸確認保護' });
break;
case 'full':
summary = conv({ hans: '全保护', hant: '全保護' });
break;
case 'move':
summary = conv({ hans: '移动保护', hant: '移動保護' });
break;
case 'salt':
summary = conv({ hans: '白纸保护', hant: '白紙保護' });
break;
case 'unprotect':
summary = conv({ hans: '解除保护', hant: '解除保護' });
break;
default:
statusElement.warn(conv({ hans: '未知保护类型', hant: '未知保護類別' }));
return;
}
if (Morebits.string.isInfinity(params.expiry)) {
summary = expiryText + summary;
} else {
summary += expiryText;
}
rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ ' + summary);
rppPage.setChangeTags(Twinkle.changeTags);
rppPage.setPageText(text);
rppPage.save();
}
};
Twinkle.protect.formatProtectionDescription = function(protectionLevels) {
var protectionNode = [];
if (!$.isEmptyObject(protectionLevels)) {
$.each(protectionLevels, function(type, settings) {
var label;
switch (type) {
case 'edit':
label = conv({ hans: '编辑', hant: '編輯' });
break;
case 'move':
label = conv({ hans: '移动', hant: '移動' });
break;
case 'create':
label = conv({ hans: '创建', hant: '建立' });
break;
case 'upload':
label = conv({ hans: '上传', hant: '上傳' });
break;
default:
label = type;
break;
}
var level;
switch (settings.level) {
case 'autoconfirmed':
level = conv({ hans: '仅允许自动确认用户', hant: '僅允許自動確認使用者' });
break;
case 'extendedconfirmed':
level = conv({ hans: '仅允许延伸确认用户', hant: '僅允許延伸確認使用者' });
break;
case 'templateeditor':
level = conv({ hans: '仅模板编辑员和管理员', hant: '僅模板編輯員和管理員' });
break;
case 'sysop':
level = conv({ hans: '仅管理员', hant: '僅管理員' });
break;
default:
level = settings.level;
break;
}
protectionNode.push($('<b>' + label + ':' + level + '</b>')[0]);
if (Morebits.string.isInfinity(settings.expiry)) {
protectionNode.push(conv({ hans: '(无限期)', hant: '(無限期)' }));
} else {
protectionNode.push(conv({ hans: '(过期:', hant: '(過期:' }) + new Morebits.date(settings.expiry).calendar('utc') + ')');
}
if (settings.cascade) {
protectionNode.push(conv({ hans: '(连锁)', hant: '(連鎖)' }));
}
});
} else {
protectionNode.push($('<b>' + conv({ hans: '无保护', hant: '無保護' }) + '</b>')[0]);
}
return protectionNode;
};
Twinkle.addInitCallback(Twinkle.protect, 'protect');
})(jQuery);
// </nowiki>
9f1f747d0c5ca94435441175cb8f288a62d9f2e8
MediaWiki:Gadget-twinklestub.js
8
162
326
2023-11-06T13:17:33Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklestub.js: Tag module
****************************************
* Mode of invocation: Tab ("Stub")
* Active on: Existing articles
* Config directives in: FriendlyConfig
* Note: customised friendlytag module (for SEWP)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.stub = function friendlytag() {
if (Morebits.isPageRedirect()) {
// Skip
// article/draft article tagging
} else if (((mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 118) && mw.config.get('wgCurRevisionId')) || (Morebits.pageNameNorm === Twinkle.getPref('sandboxPage'))) {
Twinkle.stub.mode = conv({ hans: '条目', hant: '條目' });
Twinkle.addPortletLink(Twinkle.stub.callback, '小作品', 'friendly-tag', conv({ hans: '标记小作品', hant: '標記小作品' }));
}
};
Twinkle.stub.callback = function friendlytagCallback() {
var Window = new Morebits.simpleWindow(630, Twinkle.stub.mode === 'article' ? 450 : 400);
Window.setScriptName('Twinkle');
Window.addFooterLink('小作品說明', 'Wikipedia:小作品');
Window.addFooterLink(conv({ hans: '小作品设置', hant: '小作品設定' }), 'WP:TW/PREF#stub');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#stub');
var form = new Morebits.quickForm(Twinkle.stub.callback.evaluate);
if (document.getElementsByClassName('patrollink').length) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '标记页面为已巡查', hant: '標記頁面為已巡查' }),
value: 'patrolPage',
name: 'patrolPage',
checked: Twinkle.getPref('markStubbedPagesAsPatrolled')
}
]
});
}
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
Window.setTitle(conv({ hans: '条目小作品标记', hant: '條目小作品標記' }));
form.append({
type: 'select',
name: 'sortorder',
label: conv({ hans: '查看列表:', hant: '檢視列表:' }),
tooltip: conv({ hans: '您可以在Twinkle参数设置(WP:TWPREFS)中更改此项。', hant: '您可以在Twinkle偏好設定(WP:TWPREFS)中更改此項。' }),
event: Twinkle.stub.updateSortOrder,
list: [
{ type: 'option', value: 'cat', label: conv({ hans: '按类型', hant: '按類別' }), selected: Twinkle.getPref('stubArticleSortOrder') === 'cat' },
{ type: 'option', value: 'alpha', label: '按字母', selected: Twinkle.getPref('stubArticleSortOrder') === 'alpha' }
]
});
form.append({ type: 'div', id: 'tagWorkArea' });
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
if (Twinkle.stub.mode === '条目' || Twinkle.stub.mode === '條目') {
// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sortorder.dispatchEvent(evt);
}
};
Twinkle.stub.checkedTags = [];
Twinkle.stub.updateSortOrder = function(e) {
var sortorder = e.target.value;
Twinkle.stub.checkedTags = e.target.form.getChecked('articleTags');
if (!Twinkle.stub.checkedTags) {
Twinkle.stub.checkedTags = [];
}
var container = new Morebits.quickForm.element({ type: 'fragment' });
// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: '{{' + tag + '}}: ' + description };
if (Twinkle.stub.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
return checkbox;
};
// append any custom tags
if (Twinkle.getPref('customStubList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
var customcheckboxes = [];
$.each(Twinkle.getPref('customStubList'), function(_, item) {
customcheckboxes.push(makeCheckbox(item.value, item.label));
});
container.append({
type: 'checkbox',
name: 'articleTags',
list: customcheckboxes
});
}
// categorical sort order
if (sortorder === 'cat') {
// function to iterate through the tags and create a checkbox for each one
var doCategoryCheckboxes = function(subdiv, array) {
var checkboxes = [];
$.each(array, function(k, tag) {
var description = Twinkle.stub.article.tags[tag];
checkboxes.push(makeCheckbox(tag, description));
});
subdiv.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
};
var i = 0;
// go through each category and sub-category and append lists of checkboxes
$.each(Twinkle.stub.article.tagCategories, function(title, content) {
container.append({ type: 'header', id: 'tagHeader' + i, label: title });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv' + i++ });
if ($.isArray(content)) {
doCategoryCheckboxes(subdiv, content);
} else {
$.each(content, function(subtitle, subcontent) {
subdiv.append({ type: 'div', label: [Morebits.htmlNode('b', subtitle)] });
doCategoryCheckboxes(subdiv, subcontent);
});
}
});
// alphabetical sort order
} else {
var checkboxes = [];
$.each(Twinkle.stub.article.tags, function(tag, description) {
checkboxes.push(makeCheckbox(tag, description));
});
container.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
}
var $workarea = $(e.target.form).find('div#tagWorkArea');
var rendered = container.render();
$workarea.empty().append(rendered);
// style adjustments
$workarea.find('h5').css({ 'font-size': '110%' });
$workarea.find('h5:not(:first-child)').css({ 'margin-top': '1em' });
$workarea.find('div').filter(':has(span.quickformDescription)').css({ 'margin-top': '0.4em' });
// add a link to each template's description page
$.each(Morebits.quickForm.getElements(e.target.form, 'articleTags'), function(index, checkbox) {
var $checkbox = $(checkbox);
var link = Morebits.htmlNode('a', '>');
link.setAttribute('class', 'tag-template-link');
link.setAttribute('href', mw.util.getUrl('Template:' +
Morebits.string.toUpperCaseFirstChar(checkbox.values)));
link.setAttribute('target', '_blank');
$checkbox.parent().append(['\u00A0', link]);
});
};
// Tags for ARTICLES start here
Twinkle.stub.article = {};
// A list of all article tags, in alphabetical order
// To ensure tags appear in the default "categorized" view, add them to the tagCategories hash below.
Twinkle.stub.article.tags = {
'actor-stub': conv({ hans: '演员', hant: '演員' }),
'asia-stub': conv({ hans: '亚洲', hant: '亞洲' }),
'bio-stub': conv({ hans: '人物', hant: '人物' }),
'biology-stub': conv({ hans: '生物学', hant: '生物學' }),
'chem-stub': conv({ hans: '化学', hant: '化學' }),
'europe-stub': conv({ hans: '欧洲', hant: '歐洲' }),
'expand list': conv({ hans: '未完成列表', hant: '未完成列表' }),
'food-stub': conv({ hans: '食物', hant: '食物' }),
'france-geo-stub': conv({ hans: '法国地理', hant: '法國地理' }),
'geo-stub': conv({ hans: '地理位置', hant: '地理位置' }),
'hist-stub': conv({ hans: '历史或历史学', hant: '歷史或歷史學' }),
'JP-stub': conv({ hans: '日本', hant: '日本' }),
'lit-stub': conv({ hans: '文学', hant: '文學' }),
'math-stub': conv({ hans: '数学', hant: '數學' }),
'med-stub': conv({ hans: '医学', hant: '醫學' }),
'mil-stub': conv({ hans: '军事', hant: '軍事' }),
'movie-stub': conv({ hans: '电影', hant: '電影' }),
'music-stub': conv({ hans: '音乐', hant: '音樂' }),
'physics-stub': conv({ hans: '物理学', hant: '物理學' }),
'politic-stub': conv({ hans: '政治', hant: '政治' }),
'religion-stub': conv({ hans: '宗教', hant: '宗教' }),
'science-stub': conv({ hans: '科学', hant: '科學' }),
'sport-stub': conv({ hans: '体育', hant: '體育' }),
'stub': conv({ hans: '通用小作品', hant: '通用小作品' }),
'switzerland-stub': conv({ hans: '瑞士', hant: '瑞士' }),
'tech-stub': conv({ hans: '科技', hant: '科技' }),
'transp-stub': conv({ hans: '交通', hant: '交通' }),
'TV-stub': conv({ hans: '电视', hant: '電視' }),
'UK-stub': conv({ hans: '英国', hant: '英國' }),
'US-bio-stub': conv({ hans: '美国人物', hant: '美國人物' }),
'US-geo-stub': conv({ hans: '美国地理', hant: '美國地理' }),
'US-stub': conv({ hans: '美国', hant: '美國' }),
'weather-stub': conv({ hans: '天气和特别的天气事件', hant: '天氣和特別的天氣事件' })
};
// A list of tags in order of category
// Tags should be in alphabetical order within the categories
// Add new categories with discretion - the list is long enough as is!
Twinkle.stub.article.tagCategories = {
[conv({ hans: '通用模板', hant: '通用模板' })]: [
'stub',
'expand list'
],
[conv({ hans: '国家和地理', hant: '國家和地理' })]: [
'asia-stub',
'europe-stub',
'france-geo-stub',
'geo-stub',
'JP-stub',
'switzerland-stub',
'UK-stub',
'US-bio-stub',
'US-geo-stub',
'US-stub'
],
[conv({ hans: '杂项', hant: '雜項' })]: [
'food-stub',
'hist-stub',
'mil-stub',
'politic-stub',
'religion-stub',
'transp-stub'
],
[conv({ hans: '人物', hant: '人物' })]: [
'actor-stub',
'bio-stub',
'US-bio-stub'
],
[conv({ hans: '科学', hant: '科學' })]: [
'biology-stub',
'chem-stub',
'math-stub',
'med-stub',
'physics-stub',
'science-stub',
'weather-stub'
],
[conv({ hans: '体育', hant: '體育' })]: [
'sport-stub'
],
[conv({ hans: '技术', hant: '技術' })]: [
'tech-stub'
],
[conv({ hans: '艺术', hant: '藝術' })]: [
'actor-stub',
'lit-stub',
'movie-stub',
'music-stub',
'TV-stub'
]
};
/* eslint-enable quote-props */
// Tags for REDIRECTS start here
Twinkle.stub.callbacks = {
main: function(pageobj) {
var params = pageobj.getCallbackParameters(),
tagRe, summaryText = '加入',
tags = [], groupableTags = [], i, totalTags;
// Remove tags that become superfluous with this action
var pageText = pageobj.getPageText();
var addTag = function friendlytagAddTag(tagIndex, tagName) {
pageText += '\n{{' + tagName + '}}';
if (tagIndex > 0) {
if (tagIndex === (totalTags - 1)) {
summaryText += '和';
} else if (tagIndex < (totalTags - 1)) {
summaryText += '、';
}
}
summaryText += '{{[[';
summaryText += tagName.indexOf(':') !== -1 ? tagName : 'Template:' + tagName + '|' + tagName;
summaryText += ']]}}';
};
// Check for preexisting tags and separate tags into groupable and non-groupable arrays
for (i = 0; i < params.tags.length; i++) {
tagRe = new RegExp('(\\{\\{' + params.tags[i] + '(\\||\\}\\}))', 'im');
if (!tagRe.exec(pageText)) {
tags = tags.concat(params.tags[i]);
} else {
Morebits.status.info(
conv({ hans: '信息', hant: '資訊' }),
conv({
hans: '在页面上找到{{' + params.tags[i] + '}}…跳过',
hant: '在頁面上找到{{' + params.tags[i] + '}}…跳過'
}));
}
}
tags = tags.concat(groupableTags);
tags.sort();
totalTags = tags.length;
$.each(tags, addTag);
summaryText += conv({ hans: '标记到', hant: '標記到' }) + Twinkle.stub.mode;
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchStubbedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markStubbedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
}
};
Twinkle.stub.callback.evaluate = function friendlytagCallbackEvaluate(e) {
var form = e.target;
var params = {};
if (form.patrolPage) {
params.patrol = form.patrolPage.checked;
}
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
params.tags = form.getChecked('articleTags');
params.group = false;
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
if (!params.tags.length) {
alert(conv({ hans: '必须选择至少一个标记!', hant: '必須選擇至少一個標記!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成,将在几秒内刷新页面', hant: '標記完成,將在幾秒內重新整理頁面' });
if (Twinkle.stub.mode === '重定向') {
Morebits.wiki.actionCompleted.followRedirect = false;
}
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '正在标记', hant: '正在標記' }) + Twinkle.stub.mode);
wikipedia_page.setCallbackParameters(params);
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
/* falls through */
case '重定向':
wikipedia_page.load(Twinkle.stub.callbacks.main);
return;
case '文件':
case '檔案':
wikipedia_page.load(Twinkle.stub.callbacks.file);
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
};
Twinkle.addInitCallback(Twinkle.stub, 'stub');
})(jQuery);
// </nowiki>
e50d97a516060cfc8907a60626c14210160dbfcd
MediaWiki:Gadget-twinkleunlink.js
8
164
330
2023-11-06T13:17:36Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleunlink.js: Unlink module
****************************************
* Mode of invocation: Tab ("Unlink")
* Active on: Non-special pages, except Wikipedia:Sandbox
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.unlink = function twinkleunlink() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageName') === Twinkle.getPref('sandboxPage') || !Morebits.userIsSysop) {
return;
}
Twinkle.addPortletLink(Twinkle.unlink.callback, conv({ hans: '消链', hant: '消連' }), 'tw-unlink', conv({ hans: '取消到本页的链接', hant: '取消到本頁的連結' }));
};
// the parameter is used when invoking unlink from admin speedy
Twinkle.unlink.callback = function(presetReason) {
var fileSpace = mw.config.get('wgNamespaceNumber') === 6;
var Window = new Morebits.simpleWindow(600, 440);
Window.setTitle(conv({ hans: '取消链入', hant: '取消連入' }) + (fileSpace ? conv({ hans: '和文件使用', hant: '和檔案使用' }) : ''));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '链入设置', hant: '連入設定' }), 'WP:TW/PREF#unlink');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#unlink');
var form = new Morebits.quickForm(Twinkle.unlink.callback.evaluate);
// prepend some documentation: files are commented out, while any
// display text is preserved for links (otherwise the link itself is used)
var linkTextBefore = Morebits.htmlNode('code', '[[' + (fileSpace ? ':' : '') + Morebits.pageNameNorm + conv({ hans: '|链接文字]]', hant: '|連結文字]]' }));
var linkTextAfter = Morebits.htmlNode('code', conv({ hans: '链接文字', hant: '連結文字' }));
var linkPlainBefore = Morebits.htmlNode('code', '[[' + Morebits.pageNameNorm + ']]');
var linkPlainAfter;
if (fileSpace) {
linkPlainAfter = Morebits.htmlNode('code', '<!-- [[' + Morebits.pageNameNorm + ']] -->');
} else {
linkPlainAfter = Morebits.htmlNode('code', Morebits.pageNameNorm);
}
[linkTextBefore, linkTextAfter, linkPlainBefore, linkPlainAfter].forEach(function(node) {
node.style.fontFamily = 'monospace';
node.style.fontStyle = 'normal';
});
form.append({
type: 'div',
style: 'margin-bottom: 0.5em',
label: [
conv({ hans: '这个工具可以取消所有指向该页的链接(“链入”)', hant: '這個工具可以取消所有指向該頁的連結(「連入」)' }) +
(fileSpace ? conv({ hans: ',或通过加入<!-- -->注释标记隐藏所有对此文件的使用', hant: ',或透過加入<!-- -->注釋標記隱藏所有對此檔案的使用' }) : '') +
'。例如:',
linkTextBefore, conv({ hans: '将会变成', hant: '將會變成' }), linkTextAfter, ',',
linkPlainBefore, conv({ hans: '将会变成', hant: '將會變成' }), linkPlainAfter, conv({ hans: '。请小心使用。', hant: '。請小心使用。' })
]
});
form.append({
type: 'input',
name: 'reason',
label: '理由:',
value: presetReason ? presetReason : '',
size: 60
});
var query = {
action: 'query',
list: 'backlinks',
bltitle: mw.config.get('wgPageName'),
bllimit: 'max', // 500 is max for normal users, 5000 for bots and sysops
blnamespace: Twinkle.getPref('unlinkNamespaces'),
rawcontinue: true,
format: 'json'
};
if (fileSpace) {
query.list += '|imageusage';
query.iutitle = query.bltitle;
query.iulimit = query.bllimit;
query.iunamespace = query.blnamespace;
} else {
query.blfilterredir = 'nonredirects';
}
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取链入', hant: '抓取連入' }), query, Twinkle.unlink.callbacks.display.backlinks);
wikipedia_api.params = { form: form, Window: Window, image: fileSpace };
wikipedia_api.post();
var root = document.createElement('div');
root.style.padding = '15px'; // just so it doesn't look broken
Morebits.status.init(root);
wikipedia_api.statelem.status(conv({ hans: '加载中…', hant: '載入中…' }));
Window.setContent(root);
Window.display();
};
Twinkle.unlink.callback.evaluate = function twinkleunlinkCallbackEvaluate(event) {
var form = event.target;
var input = Morebits.quickForm.getInputData(form);
if (!input.reason) {
alert(conv({ hans: '您必须指定取消链入的理由。', hant: '您必須指定取消連入的理由。' }));
return;
}
input.backlinks = input.backlinks || [];
input.imageusage = input.imageusage || [];
var pages = Morebits.array.uniq(input.backlinks.concat(input.imageusage));
if (!pages.length) {
alert(conv({ hans: '您必须至少选择一个要取消链入的页面。', hant: '您必須至少選擇一個要取消連入的頁面。' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var unlinker = new Morebits.batchOperation('取消' + (input.backlinks.length ? conv({ hans: '链入', hant: '連入' }) +
(input.imageusage.length ? conv({ hans: '与文件使用', hant: '與檔案使用' }) : '') : conv({ hans: '文件使用', hant: '檔案使用' })));
unlinker.setOption('preserveIndividualStatusLines', true);
unlinker.setPageList(pages);
var params = { reason: input.reason, unlinker: unlinker };
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '在页面“', hant: '在頁面「' }) + pageName + conv({ hans: '”中取消链入', hant: '」中取消連入' }));
wikipedia_page.setBotEdit(true); // unlink considered a floody operation
wikipedia_page.setCallbackParameters($.extend({
doBacklinks: input.backlinks.indexOf(pageName) !== -1,
doImageusage: input.imageusage.indexOf(pageName) !== -1
}, params));
wikipedia_page.load(Twinkle.unlink.callbacks.unlinkBacklinks);
});
};
Twinkle.unlink.callbacks = {
display: {
backlinks: function twinkleunlinkCallbackDisplayBacklinks(apiobj) {
var response = apiobj.getResponse();
var havecontent = false;
var list, namespaces, i;
if (apiobj.params.image) {
var imageusage = response.query.imageusage.sort(Twinkle.sortByNamespace);
list = [];
for (i = 0; i < imageusage.length; ++i) {
// Label made by Twinkle.generateBatchPageLinks
list.push({ label: '', value: imageusage[i].title, checked: true });
}
if (!list.length) {
apiobj.params.form.append({ type: 'div', label: conv({ hans: '未找到文件使用。', hant: '未找到檔案使用。' }) });
} else {
apiobj.params.form.append({ type: 'header', label: conv({ hans: '文件使用', hant: '檔案使用' }) });
namespaces = [];
$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
namespaces.push(v === '0' ? conv({ hans: '(条目)', hant: '(條目)' }) : mw.config.get('wgFormattedNamespaces')[v]);
});
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '已选择的命名空间:', hant: '已選擇的命名空間:' }) + namespaces.join('、'),
tooltip: conv({ hans: '您可在Twinkle属性中更改这个,请参见[[WP:TWPREFS]]', hant: '您可在Twinkle屬性中更改這個,請參見[[WP:TWPREFS]]' })
});
if (response['query-continue'] && response['query-continue'].imageusage) {
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '显示前', hant: '顯示前' }) + mw.language.convertNumber(list.length) + conv({ hans: '个文件使用。', hant: '個檔案使用。' })
});
}
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'imageusage')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'imageusage')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'imageusage',
shiftClickSupport: true,
list: list
});
havecontent = true;
}
}
var backlinks = response.query.backlinks.sort(Twinkle.sortByNamespace);
if (backlinks.length > 0) {
list = [];
for (i = 0; i < backlinks.length; ++i) {
// Label made by Twinkle.generateBatchPageLinks
list.push({ label: '', value: backlinks[i].title, checked: true });
}
apiobj.params.form.append({ type: 'header', label: conv({ hans: '链入', hant: '連入' }) });
namespaces = [];
$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
namespaces.push(v === '0' ? conv({ hans: '(条目)', hant: '(條目)' }) : mw.config.get('wgFormattedNamespaces')[v]);
});
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '已选择的命名空间:', hant: '已選擇的命名空間:' }) + namespaces.join('、'),
tooltip: conv({ hans: '您可在Twinkle属性中更改这个,请参见[[WP:TWPREFS]]', hant: '您可在Twinkle屬性中更改這個,請參見[[WP:TWPREFS]]' })
});
if (response['query-continue'] && response['query-continue'].backlinks) {
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '显示前', hant: '顯示前' }) + mw.language.convertNumber(list.length) + conv({ hans: '个链入。', hant: '個連入。' })
});
}
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'backlinks')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'backlinks')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'backlinks',
shiftClickSupport: true,
list: list
});
havecontent = true;
} else {
apiobj.params.form.append({ type: 'div', label: conv({ hans: '未找到链入。', hant: '未找到連入。' }) });
}
if (havecontent) {
apiobj.params.form.append({ type: 'submit' });
}
var result = apiobj.params.form.render();
apiobj.params.Window.setContent(result);
Morebits.quickForm.getElements(result, 'backlinks').forEach(Twinkle.generateBatchPageLinks);
Morebits.quickForm.getElements(result, 'imageusage').forEach(Twinkle.generateBatchPageLinks);
}
},
unlinkBacklinks: function twinkleunlinkCallbackUnlinkBacklinks(pageobj) {
var oldtext = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var wikiPage = new Morebits.wikitext.page(oldtext);
var summaryText = '', warningString = false;
var text;
// remove image usages
if (params.doImageusage) {
text = wikiPage.commentOutImage(mw.config.get('wgTitle'), conv({ hans: '注释', hant: '注釋' })).getText();
// did we actually make any changes?
if (text === oldtext) {
warningString = conv({ hans: '文件使用', hant: '檔案使用' });
} else {
summaryText = conv({ hans: '注释文件使用', hant: '注釋檔案使用' });
oldtext = text;
}
}
// remove backlinks
if (params.doBacklinks) {
text = wikiPage.removeLink(Morebits.pageNameNorm).getText();
// did we actually make any changes?
if (text === oldtext) {
warningString = warningString ? conv({ hans: '取消链入或文件使用', hant: '取消連入或檔案使用' }) : conv({ hans: '取消链入', hant: '取消連入' });
} else {
summaryText = (summaryText ? summaryText + ' / ' : '') + conv({ hans: '取消链结到', hant: '取消連結到' });
oldtext = text;
}
}
if (warningString) {
// nothing to do!
pageobj.getStatusElement().error(conv({ hans: '未能在页面上找到', hant: '未能在頁面上找到' }) + warningString + '。');
params.unlinker.workerFailure(pageobj);
return;
}
pageobj.setPageText(text);
pageobj.setEditSummary(summaryText + conv({ hans: '“', hant: '「' }) + Morebits.pageNameNorm + conv({ hans: '”:', hant: '」:' }) + params.reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
}
};
Twinkle.addInitCallback(Twinkle.unlink, 'unlink');
})(jQuery);
// </nowiki>
86b24bf86cc443470df944acfd46b80f310b8cc6
MediaWiki:Gadget-twinklewarn.js
8
152
306
2023-11-06T13:17:40Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklewarn.js: Warn module
****************************************
* Mode of invocation: Tab ("Warn")
* Active on: Any page with relevant user name (userspace, contribs,
* etc.), as well as the rollback success page
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.warn = function twinklewarn() {
if (Morebits.wiki.flow.relevantUserName()) {
Twinkle.addPortletLink(Twinkle.warn.callback, '警告', 'tw-warn', conv({ hans: '警告或提醒用户', hant: '警告或提醒使用者' }));
if (Twinkle.getPref('autoMenuAfterRollback') &&
mw.config.get('wgNamespaceNumber') === 3 &&
mw.util.getParamValue('vanarticle') &&
!mw.util.getParamValue('friendlywelcome') &&
!mw.util.getParamValue('noautowarn')) {
Twinkle.warn.callback();
}
}
// Modify URL of talk page on rollback success pages, makes use of a
// custom message box in [[MediaWiki:Rollback-success]]
if (mw.config.get('wgAction') === 'rollback') {
var $vandalTalkLink = $('#mw-rollback-success').find('.mw-usertoollinks a').first();
if ($vandalTalkLink.length) {
Twinkle.warn.makeVandalTalkLink($vandalTalkLink, Morebits.pageNameNorm);
$vandalTalkLink.css('font-weight', 'bold');
}
}
if (mw.config.get('wgCanonicalSpecialPageName') === 'AbuseLog' && mw.config.get('wgAbuseFilterVariables') !== null) {
var afTalkLink = $('.mw-usertoollinks-talk').first();
if (afTalkLink.length) {
Twinkle.warn.makeVandalTalkLink(afTalkLink, mw.config.get('wgAbuseFilterVariables').page_prefixedtitle);
afTalkLink.css('font-weight', 'bold');
}
}
// Override the mw.notify function to allow us to inject a link into the
// rollback success popup. Only users with the 'rollback' right need this,
// but we have no nice way of knowing who has that right (what with global
// groups and the like)
/*
else if( mw.config.get('wgAction') === 'history' ) {
mw.notifyOriginal = mw.notify;
mw.notify = function mwNotifyTwinkleOverride(message, options) {
// This is a horrible, awful hack to add a link to the rollback success
// popup. All other notification popups should be left untouched.
// It won't work for people whose user language is not English.
// As it's a hack, it's liable to stop working or break sometimes,
// particularly if the text or format of the confirmation message
// (MediaWiki:Rollback-success-notify) changes.
var regexMatch;
if ( options && options.title && mw.msg && options.title === mw.msg('actioncomplete') &&
message && $.isArray(message) && message[0] instanceof HTMLParagraphElement &&
(regexMatch = /^(?:回退|還原|取消|撤销|撤銷)(.+)(?:编辑|編輯|做出的編輯|做出的编辑|做出的修订版本|做出的修訂版本)/.exec(message[0].innerText))
) {
// Create a nicely-styled paragraph to place the link in
var $p = $('<p/>');
$p.css("margin", "0.5em -1.5em -1.5em");
$p.css("padding", "0.5em 1.5em 0.8em");
$p.css("border-top", "1px #666 solid");
$p.css("cursor", "default");
$p.click(function(e) { e.stopPropagation(); });
// Create the new talk link and append it to the end of the message
var $vandalTalkLink = $('<a/>');
$vandalTalkLink.text("用Twinkle警告用户");
//$vandalTalkLink.css("display", "block");
$vandalTalkLink.attr("href", mw.util.getUrl("User talk:" + regexMatch[1]));
Twinkle.warn.makeVandalTalkLink($vandalTalkLink);
$p.append($vandalTalkLink);
message[0].appendChild($p.get()[0]);
// Don't auto-hide the notification. It only stays around for 5 seconds by
// default, which might not be enough time for the user to read it and
// click the link
options.autoHide = false;
}
mw.notifyOriginal.apply(mw, arguments);
};
}
*/
// for testing, use:
// mw.notify([ $("<p>Reverted edits by foo; changed</p>")[0] ], { title: mw.msg('actioncomplete') } );
};
Twinkle.warn.makeVandalTalkLink = function($vandalTalkLink, pagename) {
$vandalTalkLink.wrapInner($('<span/>').attr('title', conv({ hans: '如果合适,您可以用Twinkle在该用户讨论页上做出警告。', hant: '如果合適,您可以用Twinkle在該使用者討論頁上做出警告。' })));
var extraParam = 'vanarticle=' + mw.util.rawurlencode(pagename);
var href = $vandalTalkLink.attr('href');
if (href.indexOf('?') === -1) {
$vandalTalkLink.attr('href', href + '?' + extraParam);
} else {
$vandalTalkLink.attr('href', href + '&' + extraParam);
}
};
// Used to close window when switching to ARV in autolevel
Twinkle.warn.dialog = null;
Twinkle.warn.callback = function twinklewarnCallback() {
if (Morebits.wiki.flow.relevantUserName() === mw.config.get('wgUserName') &&
!confirm(conv({ hans: '您将要警告自己!您确定要继续吗?', hant: '您將要警告自己!您確定要繼續嗎?' }))) {
return;
}
var dialog;
Twinkle.warn.dialog = new Morebits.simpleWindow(600, 440);
dialog = Twinkle.warn.dialog;
dialog.setTitle(conv({ hans: '警告、提醒用户', hant: '警告、提醒使用者' }));
dialog.setScriptName('Twinkle');
dialog.addFooterLink(conv({ hans: '选择警告级别', hant: '選擇警告級別' }), 'WP:WARN');
dialog.addFooterLink(conv({ hans: '警告设置', hant: '警告設定' }), 'WP:TW/PREF#warn');
dialog.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#warn');
var form = new Morebits.quickForm(Twinkle.warn.callback.evaluate);
var main_select = form.append({
type: 'field',
label: conv({ hans: '选择要发送的警告或提醒类型', hant: '選擇要傳送的警告或提醒類別' }),
tooltip: conv({ hans: '首先选择一组,再选择具体的警告模板。', hant: '首先選擇一組,再選擇具體的警告模板。' })
});
var main_group = main_select.append({
type: 'select',
name: 'main_group',
tooltip: conv({ hans: '您可在Twinkle参数设置中设置默认选择的选项', hant: '您可在Twinkle偏好設定中設定預設選擇的選項' }),
event: Twinkle.warn.callback.change_category
});
var defaultGroup = parseInt(Twinkle.getPref('defaultWarningGroup'), 10);
main_group.append({ type: 'option', label: conv({ hans: '自动选择层级(1-4)', hant: '自動選擇層級(1-4)' }), value: 'autolevel', selected: defaultGroup === 11 });
main_group.append({ type: 'option', label: '1:提醒', value: 'level1', selected: defaultGroup === 1 });
main_group.append({ type: 'option', label: '2:注意', value: 'level2', selected: defaultGroup === 2 });
main_group.append({ type: 'option', label: '3:警告', value: 'level3', selected: defaultGroup === 3 });
main_group.append({ type: 'option', label: conv({ hans: '4:最后警告', hant: '4:最後警告' }), value: 'level4', selected: defaultGroup === 4 });
main_group.append({ type: 'option', label: '4im:唯一警告', value: 'level4im', selected: defaultGroup === 5 });
if (Twinkle.getPref('combinedSingletMenus')) {
main_group.append({ type: 'option', label: conv({ hans: '单层级消息', hant: '單層級訊息' }), value: 'singlecombined', selected: defaultGroup === 6 || defaultGroup === 7 });
} else {
main_group.append({ type: 'option', label: conv({ hans: '单层级提醒', hant: '單層級提醒' }), value: 'singlenotice', selected: defaultGroup === 6 });
main_group.append({ type: 'option', label: conv({ hans: '单层级警告', hant: '單層級警告' }), value: 'singlewarn', selected: defaultGroup === 7 });
}
if (Twinkle.getPref('customWarningList').length) {
main_group.append({ type: 'option', label: conv({ hans: '自定义警告', hant: '自訂警告' }), value: 'custom', selected: defaultGroup === 9 });
}
main_group.append({ type: 'option', label: '所有警告模板', value: 'kitchensink', selected: defaultGroup === 10 });
main_select.append({ type: 'select', name: 'sub_group', event: Twinkle.warn.callback.change_subcategory }); // Will be empty to begin with.
form.append({
type: 'input',
name: 'article',
label: conv({ hans: '页面链接', hant: '頁面連結' }),
value: mw.util.getParamValue('vanarticle') || '',
size: 50,
tooltip: conv({ hans: '给模板中加入一页面链接,可留空。', hant: '給模板中加入一頁面連結,可留空。' }),
placeholder: conv({ hans: '仅限一个,勿使用网址、[[ ]],可使用Special:Diff', hant: '僅限一個,勿使用網址、[[ ]],可使用Special:Diff' })
});
form.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-warn-warning-messages'
});
var more = form.append({ type: 'field', name: 'reasonGroup', label: conv({ hans: '警告信息', hant: '警告資訊' }) });
more.append({ type: 'textarea', label: conv({ hans: '可选信息:', hant: '可選資訊:' }), name: 'reason', tooltip: conv({ hans: '理由或是附加信息', hant: '理由或是附加資訊' }) });
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.warn.callbacks.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
more.append({ type: 'div', id: 'warningpreview', label: [ previewlink ] });
more.append({ type: 'div', id: 'twinklewarn-previewbox', style: 'display: none' });
more.append({ type: 'submit', label: '提交' });
var result = form.render();
dialog.setContent(result);
dialog.display();
result.main_group.root = result;
result.previewer = new Morebits.wiki.preview($(result).find('div#twinklewarn-previewbox').last()[0]);
// Potential notices for staleness and missed reverts
var message = '';
var query = {};
var vanrevid = mw.util.getParamValue('vanarticlerevid');
if (vanrevid) {
// If you tried reverting, check if *you* actually reverted
if (!mw.util.getParamValue('noautowarn') && mw.util.getParamValue('vanarticle')) { // Via fluff link
query = {
action: 'query',
titles: mw.util.getParamValue('vanarticle'),
prop: 'revisions',
rvstartid: vanrevid,
rvlimit: 2,
rvdir: 'newer',
rvprop: 'user'
};
new Morebits.wiki.api(conv({ hans: '检查您是否成功回退该页面', hant: '檢查您是否成功回退該頁面' }), query, function (apiobj) {
var revertUser = $(apiobj.getResponse()).find('revisions rev')[1].getAttribute('user');
if (revertUser && revertUser !== mw.config.get('wgUserName')) {
message += conv({ hans: '其他人回退了该页面,并可能已经警告该用户。', hant: '其他人回退了該頁面,並可能已經警告該使用者。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}).post();
}
// Confirm edit wasn't too old for a warning
var checkStale = function(vantimestamp) {
var revDate = new Morebits.date(vantimestamp);
if (vantimestamp && revDate.isValid()) {
if (revDate.add(24, 'hours').isBefore(new Date())) {
message += conv({ hans: '这笔编辑是在24小时前做出的,现在警告可能已过时。', hant: '這筆編輯是在24小時前做出的,現在警告可能已過時。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}
};
var vantimestamp = mw.util.getParamValue('vantimestamp');
// Provided from a fluff module-based revert, no API lookup necessary
if (vantimestamp) {
checkStale(vantimestamp);
} else {
query = {
action: 'query',
prop: 'revisions',
rvprop: 'timestamp',
revids: vanrevid
};
new Morebits.wiki.api(conv({ hans: '获取版本时间戳', hant: '取得版本時間戳' }), query, function (apiobj) {
vantimestamp = $(apiobj.getResponse()).find('revisions rev').attr('timestamp');
checkStale(vantimestamp);
}).post();
}
}
if (mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName())) {
query = {
format: 'json',
action: 'query',
list: 'usercontribs',
uclimit: 1,
ucend: new Morebits.date().subtract(30, 'days').format('YYYY-MM-DDTHH:MM:ssZ', 'utc'),
ucuser: Morebits.wiki.flow.relevantUserName()
};
new Morebits.wiki.api(conv({ hans: '检查该IP用户上一笔贡献时间', hant: '檢查該IP使用者上一筆貢獻時間' }), query, function (apiobj) {
if (apiobj.getResponse().query.usercontribs.length === 0) {
message += conv({ hans: '此IP用户上一次编辑在30日之前,现在警告可能已过时。', hant: '此IP使用者上一次編輯在30日之前,現在警告可能已過時。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}).post();
}
var init = function() {
// We must init the first choice (General Note);
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.main_group.dispatchEvent(evt);
};
Morebits.wiki.flow.check('User_talk:' + Morebits.wiki.flow.relevantUserName(), function () {
Twinkle.warn.isFlow = true;
init();
}, function () {
Twinkle.warn.isFlow = false;
init();
});
};
// This is all the messages that might be dispatched by the code
// Each of the individual templates require the following information:
// label (required): A short description displayed in the dialog
// summary (required): The edit summary used. If an article name is entered, the summary is postfixed with "on [[article]]", and it is always postfixed with ". $summaryAd"
// suppressArticleInSummary (optional): Set to true to suppress showing the article name in the edit summary. Useful if the warning relates to attack pages, or some such.
Twinkle.warn.messages = {
levels: [{
category: conv({ hans: '不同类型的非建设编辑', hant: '不同類別的非建設編輯' }),
list: {
'uw-vandalism': {
level1: {
label: conv({ hans: '明显的破坏', hant: '明顯的破壞' }),
summary: conv({ hans: '提醒:明显破坏', hant: '提醒:明顯破壞' })
},
level2: {
label: conv({ hans: '明显的破坏', hant: '明顯的破壞' }),
summary: conv({ hans: '注意:明显破坏', hant: '注意:明顯破壞' })
},
level3: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '警告:恶意破坏', hant: '警告:惡意破壞' })
},
level4: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '最后警告:恶意破坏', hant: '最後警告:惡意破壞' })
},
level4im: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '唯一警告:恶意破坏', hant: '唯一警告:惡意破壞' })
}
},
'uw-test': {
level1: {
label: conv({ hans: '进行编辑测试而未及时清理', hant: '進行編輯測試而未及時清理' }),
summary: conv({ hans: '提醒:进行编辑测试而未及时清理', hant: '提醒:進行編輯測試而未及時清理' })
},
level2: {
label: conv({ hans: '进行损毁性的编辑测试', hant: '進行損毀性的編輯測試' }),
summary: conv({ hans: '注意:进行编辑测试', hant: '注意:進行編輯測試' })
},
level3: {
label: conv({ hans: '编辑测试', hant: '編輯測試' }),
summary: conv({ hans: '警告:编辑测试', hant: '警告:編輯測試' })
},
level4: {
label: conv({ hans: '编辑测试', hant: '編輯測試' }),
summary: conv({ hans: '最后警告:编辑测试', hant: '最後警告:編輯測試' })
}
},
'uw-delete': {
level1: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '提醒:不恰当地移除页面内容、模板或资料', hant: '提醒:不恰當地移除頁面內容、模板或資料' })
},
level2: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '注意:不恰当地移除页面内容、模板或资料', hant: '注意:不恰當地移除頁面內容、模板或資料' })
},
level3: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '警告:不恰当地移除页面内容、模板或资料', hant: '警告:不恰當地移除頁面內容、模板或資料' })
},
level4: {
label: conv({ hans: '移除页面、移除内容或模板', hant: '移除頁面、移除內容或模板' }),
summary: conv({ hans: '最后警告:移除页面、移除内容或模板', hant: '最後警告:移除頁面、移除內容或模板' })
},
level4im: {
label: conv({ hans: '移除页面内容、模板或资料', hant: '移除頁面內容、模板或資料' }),
summary: conv({ hans: '唯一警告:移除页面内容、模板或资料', hant: '唯一警告:移除頁面內容、模板或資料' })
}
},
'uw-redirect': {
level1: {
label: conv({ hans: '创建破坏性的重定向', hant: '建立破壞性的重定向' }),
summary: conv({ hans: '提醒:创建破坏性的重定向', hant: '提醒:建立破壞性的重定向' })
},
level2: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '注意:创建恶意重定向', hant: '注意:建立惡意重定向' })
},
level3: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '警告:创建恶意重定向', hant: '警告:建立惡意重定向' })
},
level4: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '最后警告:创建恶意重定向', hant: '最後警告:建立惡意重定向' })
},
level4im: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '唯一警告:创建恶意重定向', hant: '唯一警告:建立惡意重定向' })
}
},
'uw-tdel': {
level1: {
label: conv({ hans: '在问题仍未解决的情况下移除维护性模板', hant: '在問題仍未解決的情況下移除維護性模板' }),
summary: conv({ hans: '提醒:移除维护性模板', hant: '提醒:移除維護性模板' })
},
level2: {
label: conv({ hans: '在问题仍未解决的情况下移除维护性模板', hant: '在問題仍未解決的情況下移除維護性模板' }),
summary: conv({ hans: '注意:移除维护性模板', hant: '注意:移除維護性模板' })
},
level3: {
label: conv({ hans: '移除维护性模板', hant: '移除維護性模板' }),
summary: conv({ hans: '警告:移除维护性模板', hant: '警告:移除維護性模板' })
},
level4: {
label: conv({ hans: '移除维护性模板', hant: '移除維護性模板' }),
summary: conv({ hans: '最后警告:移除维护性模板', hant: '最後警告:移除維護性模板' })
}
},
'uw-joke': {
level1: {
label: conv({ hans: '在百科全书内容中加入玩笑', hant: '在百科全書內容中加入玩笑' }),
summary: conv({ hans: '提醒:加入不当玩笑', hant: '提醒:加入不當玩笑' })
},
level2: {
label: conv({ hans: '在百科全书内容中加入玩笑', hant: '在百科全書內容中加入玩笑' }),
summary: conv({ hans: '注意:加入不当玩笑', hant: '注意:加入不當玩笑' })
},
level3: {
label: conv({ hans: '在百科全书内容中加入不当玩笑', hant: '在百科全書內容中加入不當玩笑' }),
summary: conv({ hans: '警告:在百科全书内容中加入不当玩笑', hant: '警告:在百科全書內容中加入不當玩笑' })
},
level4: {
label: conv({ hans: '在百科全书内容中加入不当玩笑', hant: '在百科全書內容中加入不當玩笑' }),
summary: conv({ hans: '最后警告:在百科全书内容中加入不当玩笑', hant: '最後警告:在百科全書內容中加入不當玩笑' })
},
level4im: {
label: conv({ hans: '加入不当玩笑', hant: '加入不當玩笑' }),
summary: conv({ hans: '唯一警告:加入不当玩笑', hant: '唯一警告:加入不當玩笑' })
}
},
'uw-create': {
level1: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '提醒:创建不当页面', hant: '提醒:建立不當頁面' })
},
level2: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '注意:创建不当页面', hant: '注意:建立不當頁面' })
},
level3: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '警告:创建不当页面', hant: '警告:建立不當頁面' })
},
level4: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '最后警告:创建不当页面', hant: '最後警告:建立不當頁面' })
},
level4im: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '唯一警告:创建不当页面', hant: '唯一警告:建立不當頁面' })
}
},
'uw-upload': {
level1: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '提醒:上传不当图像', hant: '提醒:上傳不當圖像' })
},
level2: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '注意:上传不当图像', hant: '注意:上傳不當圖像' })
},
level3: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '警告:上传不当图像', hant: '警告:上傳不當圖像' })
},
level4: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '最后警告:上传不当图像', hant: '最後警告:上傳不當圖像' })
},
level4im: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '唯一警告:上传不当图像', hant: '唯一警告:上傳不當圖像' })
}
},
'uw-image': {
level1: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '提醒:在页面中加入不当图片', hant: '提醒:在頁面中加入不當圖片' })
},
level2: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '注意:在页面中加入不当图片', hant: '注意:在頁面中加入不當圖片' })
},
level3: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '警告:在页面中加入不当图片', hant: '警告:在頁面中加入不當圖片' })
},
level4: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '最后警告:在页面中加入不当图片', hant: '最後警告:在頁面中加入不當圖片' })
},
level4im: {
label: conv({ hans: '加入不恰当的图片', hant: '加入不恰當的圖片' }),
summary: conv({ hans: '唯一警告:加入不恰当的图片', hant: '唯一警告:加入不恰當的圖片' })
}
},
'uw-nor': {
level1: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '提醒:在条目中加入原创研究', hant: '提醒:在條目中加入原創研究' })
},
level2: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '注意:在条目中加入原创研究', hant: '注意:在條目中加入原創研究' })
},
level3: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '警告:在条目中加入原创研究', hant: '警告:在條目中加入原創研究' })
}
},
'uw-politicalbias': {
level1: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '提醒:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '提醒:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level2: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '注意:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '注意:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level3: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level4: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '最后警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '最後警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level4im: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '唯一警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '唯一警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
}
}
}
},
{
category: conv({ hans: '增加商品或政治广告', hant: '增加商品或政治廣告' }),
list: {
'uw-spam': {
level1: {
label: conv({ hans: '增加不合适的外部链接', hant: '增加不合適的外部連結' }),
summary: conv({ hans: '提醒:增加不合适的外部链接', hant: '提醒:增加不合適的外部連結' })
},
level2: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '注意:增加垃圾链接', hant: '注意:增加垃圾連結' })
},
level3: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '警告:增加垃圾链接', hant: '警告:增加垃圾連結' })
},
level4: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '最后警告:增加垃圾链接', hant: '最後警告:增加垃圾連結' })
},
level4im: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '唯一警告:增加垃圾链接', hant: '唯一警告:增加垃圾連結' })
}
},
'uw-advert': {
level1: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '提醒:利用维基百科来发布广告或推广', hant: '提醒:利用維基百科來發布廣告或推廣' })
},
level2: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '注意:利用维基百科来发布广告或推广', hant: '注意:利用維基百科來發布廣告或推廣' })
},
level3: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '警告:利用维基百科来发布广告或推广', hant: '警告:利用維基百科來發布廣告或推廣' })
},
level4: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '最后警告:利用维基百科来发布广告或推广', hant: '最後警告:利用維基百科來發布廣告或推廣' })
}
},
'uw-npov': {
level1: {
label: conv({ hans: '不遵守中立的观点方针', hant: '不遵守中立的觀點方針' }),
summary: conv({ hans: '提醒:不遵守中立的观点方针', hant: '提醒:不遵守中立的觀點方針' })
},
level2: {
label: conv({ hans: '不遵守中立的观点方针', hant: '不遵守中立的觀點方針' }),
summary: conv({ hans: '注意:不遵守中立的观点方针', hant: '注意:不遵守中立的觀點方針' })
},
level3: {
label: conv({ hans: '违反中立的观点方针', hant: '違反中立的觀點方針' }),
summary: conv({ hans: '警告:违反中立的观点方针', hant: '警告:違反中立的觀點方針' })
},
level4: {
label: conv({ hans: '违反中立的观点方针', hant: '違反中立的觀點方針' }),
summary: conv({ hans: '最后警告:违反中立的观点方针', hant: '最後警告:違反中立的觀點方針' })
}
}
}
},
{
category: conv({ hans: '加插不实及/或诽谤文字', hant: '加插不實及/或誹謗文字' }),
list: {
'uw-unsourced': {
level1: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '提醒:加入没有可靠来源佐证的内容', hant: '提醒:加入沒有可靠來源佐證的內容' })
},
level2: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '注意:加入没有可靠来源佐证的内容', hant: '注意:加入沒有可靠來源佐證的內容' })
},
level3: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '警告:加入没有可靠来源佐证的内容', hant: '警告:加入沒有可靠來源佐證的內容' })
}
},
'uw-error': {
level1: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '提醒:故意加入不实内容', hant: '提醒:故意加入不實內容' })
},
level2: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '注意:故意加入不实内容', hant: '注意:故意加入不實內容' })
},
level3: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '警告:故意加入不实内容', hant: '警告:故意加入不實內容' })
}
},
'uw-biog': {
level1: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' }),
summary: conv({ hans: '提醒:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '提醒:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level2: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' }),
summary: conv({ hans: '注意:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '注意:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level3: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且带有争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且帶有爭議的內容' }),
summary: conv({ hans: '警告:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '警告:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level4: {
label: conv({ hans: '加入有关在生人物而又缺乏来源的资料', hant: '加入有關在生人物而又缺乏來源的資料' }),
summary: conv({ hans: '最后警告:加入有关在生人物而又缺乏来源的资料', hant: '最後警告:加入有關在生人物而又缺乏來源的資料' })
},
level4im: {
label: conv({ hans: '加入有关在生人物而又缺乏来源的资料', hant: '加入有關在生人物而又缺乏來源的資料' }),
summary: conv({ hans: '唯一警告:加入有关在生人物而又缺乏来源的资料', hant: '唯一警告:加入有關在生人物而又缺乏來源的資料' })
}
},
'uw-defamatory': {
level1: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '提醒:加入诽谤内容', hant: '提醒:加入誹謗內容' })
},
level2: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '注意:加入诽谤内容', hant: '注意:加入誹謗內容' })
},
level3: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '警告:加入诽谤内容', hant: '警告:加入誹謗內容' })
},
level4: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '最后警告:加入诽谤内容', hant: '最後警告:加入誹謗內容' })
},
level4im: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '唯一警告:加入诽谤内容', hant: '唯一警告:加入誹謗內容' })
}
}
}
},
{
category: conv({ hans: '翻译品质', hant: '翻譯品質' }),
list: {
'uw-roughtranslation': {
level1: {
label: conv({ hans: '您翻译的质量有待改善', hant: '您翻譯的質量有待改善' }),
summary: conv({ hans: '提醒:您翻译的质量有待改善', hant: '提醒:您翻譯的質量有待改善' })
},
level2: {
label: conv({ hans: '粗劣翻译', hant: '粗劣翻譯' }),
summary: conv({ hans: '注意:粗劣翻译', hant: '注意:粗劣翻譯' })
},
level3: {
label: conv({ hans: '粗劣翻译', hant: '粗劣翻譯' }),
summary: conv({ hans: '警告:粗劣翻译', hant: '警告:粗劣翻譯' })
}
}
}
},
{
category: conv({ hans: '非能接受且违反方针或指引的单方面行为或操作', hant: '非能接受且違反方針或指引的單方面行為或操作' }),
list: {
'uw-notcensored': {
level1: {
label: conv({ hans: '因为“内容使人反感”而删除条目内容', hant: '因為「內容使人反感」而刪除條目內容' }),
summary: conv({ hans: '提醒:审查条目内容', hant: '提醒:審查條目內容' })
},
level2: {
label: conv({ hans: '内容审查', hant: '內容審查' }),
summary: conv({ hans: '注意:内容审查', hant: '注意:內容審查' })
},
level3: {
label: conv({ hans: '审查内容', hant: '審查內容' }),
summary: conv({ hans: '警告:审查内容', hant: '警告:審查內容' })
}
},
'uw-mos': {
level1: {
label: conv({ hans: '不恰当的条目格式、日期、语言等', hant: '不恰當的條目格式、日期、語言等' }),
summary: conv({ hans: '提醒:不恰当的条目格式、日期、语言等', hant: '提醒:不恰當的條目格式、日期、語言等' })
},
level2: {
label: conv({ hans: '不恰当的条目格式、日期、语言等', hant: '不恰當的條目格式、日期、語言等' }),
summary: conv({ hans: '注意:不恰当的条目格式、日期、语言等', hant: '注意:不恰當的條目格式、日期、語言等' })
},
level3: {
label: conv({ hans: '违反格式、日期、语言等规定', hant: '違反格式、日期、語言等規定' }),
summary: conv({ hans: '警告:违反格式、日期、语言等规定', hant: '警告:違反格式、日期、語言等規定' })
},
level4: {
label: conv({ hans: '违反格式、日期、语言等相关规定', hant: '違反格式、日期、語言等相關規定' }),
summary: conv({ hans: '最后警告:违反格式、日期、语言等相关规定', hant: '最後警告:違反格式、日期、語言等相關規定' })
}
},
'uw-move': {
level1: {
label: conv({ hans: '无故移动条目/新名称不符合命名规范', hant: '無故移動條目/新名稱不符合命名規範' }),
summary: conv({ hans: '提醒:不恰当地移动页面', hant: '提醒:不恰當地移動頁面' })
},
level2: {
label: conv({ hans: '把页面移动到不恰当、违反命名常规或违反共识的标题', hant: '把頁面移動到不恰當、違反命名常規或違反共識的標題' }),
summary: conv({ hans: '注意:不恰当地移动页面', hant: '注意:不恰當地移動頁面' })
},
level3: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '警告:不恰当地移动页面', hant: '警告:不恰當地移動頁面' })
},
level4: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '最后警告:不恰当地移动页面', hant: '最後警告:不恰當地移動頁面' })
},
level4im: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '唯一警告:不恰当地移动页面', hant: '唯一警告:不恰當地移動頁面' })
}
},
'uw-cd': {
level1: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '提醒:清空讨论页', hant: '提醒:清空討論頁' })
},
level2: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '注意:清空讨论页', hant: '注意:清空討論頁' })
},
level3: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '警告:清空讨论页', hant: '警告:清空討論頁' })
}
},
'uw-chat': {
level1: {
label: conv({ hans: '在讨论页发表与改善条目无关的内容', hant: '在討論頁發表與改善條目無關的內容' }),
summary: conv({ hans: '提醒:在讨论页发表与改善条目无关的内容', hant: '提醒:在討論頁發表與改善條目無關的內容' })
},
level2: {
label: conv({ hans: '在讨论页发表与改善条目无关的内容', hant: '在討論頁發表與改善條目無關的內容' }),
summary: conv({ hans: '注意:在讨论页发表与改善条目无关的内容', hant: '注意:在討論頁發表與改善條目無關的內容' })
},
level3: {
label: conv({ hans: '在讨论页发表无关内容', hant: '在討論頁發表無關內容' }),
summary: conv({ hans: '警告:在讨论页发表无关内容', hant: '警告:在討論頁發表無關內容' })
},
level4: {
label: conv({ hans: '在讨论页进行不当讨论', hant: '在討論頁進行不當討論' }),
summary: conv({ hans: '最后警告:在讨论页进行不当讨论', hant: '最後警告:在討論頁進行不當討論' })
}
},
'uw-tpv': {
level1: {
label: '修改他人留言',
summary: '提醒:修改他人留言'
},
level2: {
label: '修改他人留言',
summary: '注意:修改他人留言'
},
level3: {
label: '修改他人留言',
summary: '警告:修改他人留言'
}
},
'uw-afd': {
level1: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '提醒:移除{{afd}}(页面存废讨论)模板', hant: '提醒:移除{{afd}}(頁面存廢討論)模板' })
},
level2: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '注意:移除{{afd}}(页面存废讨论)模板', hant: '注意:移除{{afd}}(頁面存廢討論)模板' })
},
level3: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '警告:移除{{afd}}(页面存废讨论)模板', hant: '警告:移除{{afd}}(頁面存廢討論)模板' })
},
level4: {
label: '移除{{afd}}模板',
summary: conv({ hans: '最后警告:移除{{afd}}模板', hant: '最後警告:移除{{afd}}模板' })
}
},
'uw-speedy': {
level1: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '提醒:移除{{delete}}(快速删除)模板', hant: '提醒:移除{{delete}}(快速刪除)模板' })
},
level2: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '注意:移除{{delete}}(快速删除)模板', hant: '注意:移除{{delete}}(快速刪除)模板' })
},
level3: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '警告:移除{{delete}}(快速删除)模板', hant: '警告:移除{{delete}}(快速刪除)模板' })
},
level4: {
label: '移除{{delete}}模板',
summary: conv({ hans: '最后警告:移除{{delete}}模板', hant: '最後警告:移除{{delete}}模板' })
}
}
}
},
{
category: conv({ hans: '对其他用户和条目的态度', hant: '對其他用戶和條目的態度' }),
list: {
'uw-npa': {
level1: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '提醒:针对用户的人身攻击', hant: '提醒:針對用戶的人身攻擊' })
},
level2: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '注意:针对用户的人身攻击', hant: '注意:針對用戶的人身攻擊' })
},
level3: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '警告:针对用户的人身攻击', hant: '警告:針對用戶的人身攻擊' })
},
level4: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '最后警告:针对用户的人身攻击', hant: '最後警告:針對用戶的人身攻擊' })
},
level4im: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '唯一警告:针对用户的人身攻击', hant: '唯一警告:針對用戶的人身攻擊' })
}
},
'uw-agf': {
level1: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '提醒:没有假定善意', hant: '提醒:沒有假定善意' })
},
level2: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '注意:没有假定善意', hant: '注意:沒有假定善意' })
},
level3: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '警告:没有假定善意', hant: '警告:沒有假定善意' })
}
},
'uw-own': {
level1: {
label: conv({ hans: '主张条目所有权', hant: '主張條目所有權' }),
summary: conv({ hans: '提醒:主张条目所有权', hant: '提醒:主張條目所有權' })
},
level2: {
label: conv({ hans: '主张条目的所有权', hant: '主張條目的所有權' }),
summary: conv({ hans: '注意:主张条目的所有权', hant: '注意:主張條目的所有權' })
},
level3: {
label: conv({ hans: '主张条目的所有权', hant: '主張條目的所有權' }),
summary: conv({ hans: '警告:主张条目的所有权', hant: '警告:主張條目的所有權' })
}
},
'uw-tempabuse': {
level1: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '提醒:不当使用警告或封禁模板', hant: '提醒:不當使用警告或封禁模板' })
},
level2: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '注意:不当使用警告或封禁模板', hant: '注意:不當使用警告或封禁模板' })
},
level3: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '警告:不当使用警告或封禁模板', hant: '警告:不當使用警告或封禁模板' })
},
level4: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '最后警告:不当使用警告或封禁模板', hant: '最後警告:不當使用警告或封禁模板' })
},
level4im: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '唯一警告:不当使用警告或封禁模板', hant: '唯一警告:不當使用警告或封禁模板' })
}
}
}
}],
singlenotice: {
'uw-2redirect': {
label: conv({ hans: '在移动页面后应该修复双重重定向', hant: '在移動頁面後應該修復雙重重定向' }),
summary: conv({ hans: '提醒:在移动页面后应该修复双重重定向', hant: '提醒:在移動頁面後應該修復雙重重定向' })
},
'uw-aiv': {
label: conv({ hans: '举报的并不是破坏者,或者举报破坏前未进行警告', hant: '舉報的並不是破壞者,或者舉報破壞前未進行警告' }),
summary: conv({ hans: '提醒:不恰当地举报破坏', hant: '提醒:不恰當地舉報破壞' })
},
'uw-articlesig': {
label: conv({ hans: '在条目中签名', hant: '在條目中簽名' }),
summary: conv({ hans: '提醒:在条目中签名', hant: '提醒:在條目中簽名' })
},
'uw-autobiography': {
label: conv({ hans: '创建自传', hant: '建立自傳' }),
summary: conv({ hans: '提醒:创建自传', hant: '提醒:建立自傳' })
},
'uw-badcat': {
label: conv({ hans: '加入错误的页面分类', hant: '加入錯誤的頁面分類' }),
summary: conv({ hans: '提醒:加入错误的页面分类', hant: '提醒:加入錯誤的頁面分類' })
},
'uw-bite': {
label: conv({ hans: '伤害新手', hant: '傷害新手' }),
summary: conv({ hans: '提醒:伤害新手', hant: '提醒:傷害新手' })
},
'uw-booktitle': {
label: conv({ hans: '没有使用书名号来标示书籍、电影、音乐专辑等', hant: '沒有使用書名號來標示書籍、電影、音樂專輯等' }),
summary: conv({ hans: '提醒:没有使用书名号来标示书籍、电影、音乐专辑等', hant: '提醒:沒有使用書名號來標示書籍、電影、音樂專輯等' })
},
'uw-c&pmove': {
label: conv({ hans: '剪贴移动', hant: '剪貼移動' }),
summary: conv({ hans: '提醒:剪贴移动', hant: '提醒:剪貼移動' })
},
'uw-chinese': {
label: conv({ hans: '请使用标准汉语沟通', hant: '請使用標準漢語溝通' }),
summary: conv({ hans: '提醒:请使用标准汉语沟通', hant: '提醒:請使用標準漢語溝通' })
},
'uw-coi': {
label: conv({ hans: '利益冲突', hant: '利益衝突' }),
summary: conv({ hans: '提醒:利益冲突', hant: '提醒:利益衝突' })
},
'uw-concovid19': {
label: conv({ hans: '违反COVID-19条目共识', hant: '違反COVID-19條目共識' }),
summary: conv({ hans: '提醒:违反COVID-19条目共识', hant: '提醒:違反COVID-19條目共識' })
},
'uw-copyright-friendly': {
label: conv({ hans: '初次加入侵犯著作权的内容', hant: '初次加入侵犯版權的內容' }),
summary: conv({ hans: '提醒:初次加入侵犯著作权的内容', hant: '提醒:初次加入侵犯版權的內容' })
},
'uw-copyviorewrite': {
label: conv({ hans: '在侵权页面直接重写条目', hant: '在侵權頁面直接重寫條目' }),
summary: conv({ hans: '提醒:在侵权页面直接重写条目', hant: '提醒:在侵權頁面直接重寫條目' })
},
'uw-crystal': {
label: conv({ hans: '加入臆测或未确认的消息', hant: '加入臆測或未確認的訊息' }),
summary: conv({ hans: '提醒:加入臆测或未确认的消息', hant: '提醒:加入臆測或未確認的訊息' })
},
'uw-csd': {
label: conv({ hans: '快速删除理由不当', hant: '快速刪除理由不當' }),
summary: conv({ hans: '提醒:快速删除理由不当', hant: '提醒:快速刪除理由不當' })
},
'uw-dab': {
label: conv({ hans: '消歧义页格式错误', hant: '消歧義頁格式錯誤' }),
summary: conv({ hans: '提醒:消歧义页格式错误', hant: '提醒:消歧義頁格式錯誤' })
},
'uw-draft': {
label: conv({ hans: '最近创建的页面被移动到草稿', hant: '最近建立的頁面被移動到草稿' }),
summary: conv({ hans: '提醒:最近创建的页面被移动到草稿', hant: '提醒:最近建立的頁面被移動到草稿' })
},
'uw-editsummary': {
label: conv({ hans: '没有使用编辑摘要', hant: '沒有使用編輯摘要' }),
summary: conv({ hans: '提醒:没有使用编辑摘要', hant: '提醒:沒有使用編輯摘要' })
},
'uw-hangon': {
label: conv({ hans: '没有在讨论页说明暂缓快速删除理由', hant: '沒有在討論頁說明暫緩快速刪除理由' }),
summary: conv({ hans: '提醒:没有在讨论页说明暂缓快速删除理由', hant: '提醒:沒有在討論頁說明暫緩快速刪除理由' })
},
'uw-lang': {
label: conv({ hans: '不必要地将文字换成简体或繁体中文', hant: '不必要地將文字換成簡體或繁體中文' }),
summary: conv({ hans: '提醒:不必要地将文字换成简体或繁体中文', hant: '提醒:不必要地將文字換成簡體或繁體中文' })
},
'uw-langmove': {
label: conv({ hans: '不必要地将标题换成简体或繁体中文', hant: '不必要地將標題換成簡體或繁體中文' }),
summary: conv({ hans: '提醒:不必要地将标题换成简体或繁体中文', hant: '提醒:不必要地將標題換成簡體或繁體中文' })
},
'uw-linking': {
label: conv({ hans: '过度加入红字链接或重复蓝字链接', hant: '過度加入紅字連結或重複藍字連結' }),
summary: conv({ hans: '提醒:过度加入红字链接或重复蓝字链接', hant: '提醒:過度加入紅字連結或重複藍字連結' })
},
'uw-minor': {
label: conv({ hans: '不适当地使用小修改选项', hant: '不適當地使用小修改選項' }),
summary: conv({ hans: '提醒:不适当地使用小修改选项', hant: '提醒:不適當地使用小修改選項' })
},
'uw-notaiv': {
label: conv({ hans: '向“当前的破坏”中报告的是用户纷争而不是破坏', hant: '向「當前的破壞」中報告的是用戶紛爭而不是破壞' }),
summary: conv({ hans: '提醒:向“当前的破坏”中报告的是用户纷争而不是破坏', hant: '提醒:向「當前的破壞」中報告的是用戶紛爭而不是破壞' })
},
'uw-notvote': {
label: conv({ hans: '我们以共识处事,而不仅仅是投票', hant: '我們以共識處事,而不僅僅是投票' }),
summary: conv({ hans: '提醒:我们以共识处事,而不仅仅是投票', hant: '提醒:我們以共識處事,而不僅僅是投票' })
},
'uw-preview': {
label: conv({ hans: '请使用预览按钮来避免不必要的错误', hant: '請使用預覽按鈕來避免不必要的錯誤' }),
summary: conv({ hans: '提醒:请使用预览按钮来避免不必要的错误', hant: '提醒:請使用預覽按鈕來避免不必要的錯誤' })
},
'uw-sandbox': {
label: conv({ hans: '移除沙盒的置顶模板{{sandbox}}', hant: '移除沙盒的置頂模板{{sandbox}}' }),
summary: conv({ hans: '提醒:移除沙盒的置顶模板{{sandbox}}', hant: '提醒:移除沙盒的置頂模板{{sandbox}}' })
},
'uw-selfrevert': {
label: conv({ hans: '感谢您自行回退自己的测试,以后不要再这样做了', hant: '感謝您自行回退自己的測試,以後不要再這樣做了' }),
summary: conv({ hans: '提醒:回退个人的测试', hant: '提醒:回退個人的測試' })
},
'uw-subst': {
label: conv({ hans: '谨记要替代模板(subst)', hant: '謹記要替代模板(subst)' }),
summary: conv({ hans: '提醒:谨记要替代模板', hant: '提醒:謹記要替代模板' })
},
'uw-talkinarticle': {
label: conv({ hans: '在条目页中留下意见', hant: '在條目頁中留下意見' }),
summary: conv({ hans: '提醒:在条目页中留下意见', hant: '提醒:在條目頁中留下意見' })
},
'uw-tilde': {
label: conv({ hans: '没有在讨论页上签名', hant: '沒有在討論頁上簽名' }),
summary: conv({ hans: '提醒:没有在讨论页上签名', hant: '提醒:沒有在討論頁上簽名' })
},
'uw-translated': {
label: conv({ hans: '翻译条目未标注原作者', hant: '翻譯條目未標註原作者' }),
summary: conv({ hans: '提醒:翻译条目未标注原作者', hant: '提醒:翻譯條目未標註原作者' })
},
'uw-uaa': {
label: conv({ hans: '向不当用户名布告板报告的用户名并不违反方针', hant: '向不當使用者名稱布告板報告的使用者名稱並不違反方針' }),
summary: conv({ hans: '提醒:向不当用户名布告板报告的用户名并不违反方针', hant: '提醒:向不當使用者名稱布告板報告的使用者名稱並不違反方針' })
},
'uw-warn': {
label: conv({ hans: '警告破坏用户', hant: '警告破壞用戶' }),
summary: conv({ hans: '提醒:警告破坏用户', hant: '提醒:警告破壞用戶' })
},
'uw-mosiw': {
label: conv({ hans: '不要使用跨语言链接', hant: '不要使用跨語言連結' }),
summary: conv({ hans: '提醒:不要使用跨语言链接', hant: '提醒:不要使用跨語言連結' })
},
'uw-badtwinkle': {
label: conv({ hans: '不恰当地使用Twinkle警告别人', hant: '不恰當地使用Twinkle警告別人' }),
summary: conv({ hans: '提醒:不恰当地使用Twinkle警告别人', hant: '提醒:不恰當地使用Twinkle警告別人' })
}
},
singlewarn: {
'uw-3rr': {
label: conv({ hans: '用户潜在违反回退不过三原则的可能性', hant: '用戶潛在違反回退不過三原則的可能性' }),
summary: conv({ hans: '警告:用户潜在违反回退不过三原则的可能性', hant: '警告:用戶潛在違反回退不過三原則的可能性' })
},
'uw-attack': {
label: conv({ hans: '创建人身攻击页面', hant: '建立人身攻擊頁面' }),
summary: conv({ hans: '警告:创建人身攻击页面', hant: '警告:建立人身攻擊頁面' }),
suppressArticleInSummary: true
},
'uw-bv': {
label: conv({ hans: '公然地破坏', hant: '公然地破壞' }),
summary: conv({ hans: '警告:公然地破坏', hant: '警告:公然地破壞' })
},
'uw-canvass': {
label: conv({ hans: '不恰当地拉票', hant: '不恰當地拉票' }),
summary: conv({ hans: '警告:不恰当地拉票', hant: '警告:不恰當地拉票' })
},
'uw-copyright': {
label: conv({ hans: '侵犯著作权', hant: '侵犯版權' }),
summary: conv({ hans: '警告:侵犯著作权', hant: '警告:侵犯版權' })
},
'uw-copyright-link': {
label: conv({ hans: '链接到有著作权的材料', hant: '連結到有版權的材料' }),
summary: conv({ hans: '警告:链接到有著作权的材料', hant: '警告:連結到有版權的材料' })
},
'uw-fakesource': {
label: conv({ hans: '虚构数据源或引文', hant: '虛構資料來源或引文' }),
summary: conv({ hans: '警告:虚构数据源或引文', hant: '警告:虛構資料來源或引文' })
},
'uw-hoax': {
label: conv({ hans: '创建恶作剧', hant: '建立惡作劇' }),
summary: conv({ hans: '警告:创建恶作剧', hant: '警告:建立惡作劇' })
},
'uw-incompletecite': {
label: conv({ hans: '列出的数据源欠缺若干详情而不易查找', hant: '列出的資料來源欠缺若干詳情而不易查找' }),
summary: conv({ hans: '警告:列出的数据源欠缺若干详情而不易查找', hant: '警告:列出的資料來源欠缺若干詳情而不易查找' })
},
'uw-legal': {
label: conv({ hans: '诉诸法律威胁', hant: '訴諸法律威脅' }),
summary: conv({ hans: '警告:诉诸法律威胁', hant: '警告:訴諸法律威脅' })
},
'uw-longterm': {
label: conv({ hans: '长期的破坏', hant: '長期的破壞' }),
summary: conv({ hans: '警告:长期的破坏', hant: '警告:長期的破壞' })
},
'uw-multipleIPs': {
label: conv({ hans: '使用多个IP地址进行破坏', hant: '使用多個IP地址進行破壞' }),
summary: conv({ hans: '警告:使用多个IP地址进行破坏', hant: '警告:使用多個IP地址進行破壞' })
},
'uw-npov-tvd': {
label: conv({ hans: '在剧集条目中加入奸角等非中立描述', hant: '在劇集條目中加入奸角等非中立描述' }),
summary: conv({ hans: '警告:在剧集条目中加入奸角等非中立描述', hant: '警告:在劇集條目中加入奸角等非中立描述' })
},
'uw-owntalk': {
label: conv({ hans: '匿名用户移除自己讨论页上7日内的讨论', hant: '匿名使用者移除自己討論頁上7日內的討論' }),
summary: conv({ hans: '警告:匿名用户移除自己讨论页上7日内的讨论', hant: '警告:匿名使用者移除自己討論頁上7日內的討論' })
},
'uw-pinfo': {
label: conv({ hans: '张贴他人隐私', hant: '張貼他人隱私' }),
summary: conv({ hans: '警告:张贴他人隐私', hant: '警告:張貼他人隱私' })
},
'uw-upv': {
label: conv({ hans: '破坏他人用户页', hant: '破壞他人用戶頁' }),
summary: conv({ hans: '警告:破坏他人用户页', hant: '警告:破壞他人用戶頁' })
},
'uw-selfinventedname': {
label: conv({ hans: '不适当地自创新名词、新译名', hant: '不適當地自創新名詞、新譯名' }),
summary: conv({ hans: '警告:不适当地自创新名词、新译名', hant: '警告:不適當地自創新名詞、新譯名' })
},
'uw-substub': {
label: conv({ hans: '创建小小作品', hant: '建立小小作品' }),
summary: conv({ hans: '警告:创建小小作品', hant: '警告:建立小小作品' })
},
'uw-username': {
label: conv({ hans: '使用不恰当的用户名', hant: '使用不恰當的用戶名' }),
summary: conv({ hans: '警告:使用不恰当的用户名', hant: '警告:使用不恰當的用戶名' }),
suppressArticleInSummary: true
},
'uw-wrongsummary': {
label: conv({ hans: '在编辑摘要制造不适当的内容', hant: '在編輯摘要製造不適當的內容' }),
summary: conv({ hans: '警告:在编辑摘要制造不适当的内容', hant: '警告:在編輯摘要製造不適當的內容' })
}
}
};
// Used repeatedly below across menu rebuilds
Twinkle.warn.prev_article = null;
Twinkle.warn.prev_reason = null;
Twinkle.warn.talkpageObj = null;
Twinkle.warn.callback.change_category = function twinklewarnCallbackChangeCategory(e) {
var value = e.target.value;
var sub_group = e.target.root.sub_group;
sub_group.main_group = value;
var old_subvalue = sub_group.value;
var old_subvalue_re;
if (old_subvalue) {
if (value === 'kitchensink') { // Exact match possible in kitchensink menu
old_subvalue_re = new RegExp(mw.util.escapeRegExp(old_subvalue));
} else {
old_subvalue = old_subvalue.replace(/\d*(im)?$/, '');
old_subvalue_re = new RegExp(mw.util.escapeRegExp(old_subvalue) + '(\\d*(?:im)?)$');
}
}
while (sub_group.hasChildNodes()) {
sub_group.removeChild(sub_group.firstChild);
}
var selected = false;
// worker function to create the combo box entries
var createEntries = function(contents, container, wrapInOptgroup, val) {
val = typeof val !== 'undefined' ? val : value; // IE doesn't support default parameters
// level2->2, singlewarn->''; also used to distinguish the
// scaled levels from singlenotice, singlewarn, and custom
var level = val.replace(/^\D+/g, '');
// due to an apparent iOS bug, we have to add an option-group to prevent truncation of text
// (search WT:TW archives for "Problem selecting warnings on an iPhone")
if (wrapInOptgroup && $.client.profile().platform === 'iphone') {
var wrapperOptgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: '可用模板'
});
wrapperOptgroup = wrapperOptgroup.render();
container.appendChild(wrapperOptgroup);
container = wrapperOptgroup;
}
$.each(contents, function(itemKey, itemProperties) {
// Skip if the current template doesn't have a version for the current level
if (!!level && !itemProperties[val]) {
return;
}
var key = typeof itemKey === 'string' ? itemKey : itemProperties.value;
var template = key + level;
var elem = new Morebits.quickForm.element({
type: 'option',
label: '{{' + template + '}}: ' + (level ? itemProperties[val].label : itemProperties.label),
value: template
});
// Select item best corresponding to previous selection
if (!selected && old_subvalue && old_subvalue_re.test(template)) {
elem.data.selected = selected = true;
}
var elemRendered = container.appendChild(elem.render());
$(elemRendered).data('messageData', itemProperties);
});
};
switch (value) {
case 'singlenotice':
case 'singlewarn':
createEntries(Twinkle.warn.messages[value], sub_group, true);
break;
case 'singlecombined':
var unSortedSinglets = $.extend({}, Twinkle.warn.messages.singlenotice, Twinkle.warn.messages.singlewarn);
var sortedSingletMessages = {};
Object.keys(unSortedSinglets).sort().forEach(function(key) {
sortedSingletMessages[key] = unSortedSinglets[key];
});
createEntries(sortedSingletMessages, sub_group, true);
break;
case 'custom':
createEntries(Twinkle.getPref('customWarningList'), sub_group, true);
break;
case 'kitchensink':
['level1', 'level2', 'level3', 'level4', 'level4im'].forEach(function(lvl) {
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
createEntries(levelGroup.list, sub_group, true, lvl);
});
});
createEntries(Twinkle.warn.messages.singlenotice, sub_group, true);
createEntries(Twinkle.warn.messages.singlewarn, sub_group, true);
createEntries(Twinkle.getPref('customWarningList'), sub_group, true);
break;
case 'level1':
case 'level2':
case 'level3':
case 'level4':
case 'level4im':
// Creates subgroup regardless of whether there is anything to place in it;
// leaves "Removal of deletion tags" empty for 4im
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: levelGroup.category
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(levelGroup.list, optgroup, false);
});
break;
case 'autolevel':
// Check user page to determine appropriate level
var autolevelProc = function() {
var wikitext = Twinkle.warn.talkpageObj.getPageText();
// history not needed for autolevel
var latest = Twinkle.warn.callbacks.dateProcessing(wikitext)[0];
// Pseudo-params with only what's needed to parse the level i.e. no messageData
var params = {
sub_group: old_subvalue,
article: e.target.root.article.value
};
var lvl = 'level' + Twinkle.warn.callbacks.autolevelParseWikitext(wikitext, params, latest)[1];
// Identical to level1, etc. above but explicitly provides the level
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: levelGroup.category
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(levelGroup.list, optgroup, false, lvl);
});
// Trigger subcategory change, add select menu, etc.
Twinkle.warn.callback.postCategoryCleanup(e);
};
if (Twinkle.warn.talkpageObj) {
autolevelProc();
} else {
if (Twinkle.warn.isFlow) {
var $noTalkPageNode = $('<strong/>', {
text: conv({ hans: '结构式讨论(Flow)不支持自动选择警告层级,请手动选择层级。', hant: '結構式討論(Flow)不支援自動選擇警告層級,請手動選擇層級。' }),
id: 'twinkle-warn-autolevel-message',
css: {color: 'red' }
});
$noTalkPageNode.insertBefore($('#twinkle-warn-warning-messages'));
// If a preview was opened while in a different mode, close it
// Should nullify the need to catch the error in preview callback
e.target.root.previewer.closePreview();
} else {
var usertalk_page = new Morebits.wiki.page('User_talk:' + Morebits.wiki.flow.relevantUserName(), conv({ hans: '加载上次警告', hant: '載入上次警告' }));
usertalk_page.setFollowRedirect(true, false);
usertalk_page.load(function(pageobj) {
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj
autolevelProc();
}, function() {
// Catch and warn if the talkpage can't load,
// most likely because it's a cross-namespace redirect
// Supersedes the typical $autolevelMessage added in autolevelParseWikitext
var $noTalkPageNode = $('<strong/>', {
text: conv({ hans: '无法加载用户讨论页,这可能是因为它是跨命名空间重定向,自动选择警告级别将不会运作。', hant: '無法載入使用者討論頁,這可能是因為它是跨命名空間重新導向,自動選擇警告級別將不會運作。' }),
id: 'twinkle-warn-autolevel-message',
css: {color: 'red' }
});
$noTalkPageNode.insertBefore($('#twinkle-warn-warning-messages'));
// If a preview was opened while in a different mode, close it
// Should nullify the need to catch the error in preview callback
e.target.root.previewer.closePreview();
});
}
}
break;
default:
alert(conv({ hans: 'twinklewarn中未知的警告组', hant: 'twinklewarn中未知的警告組' }));
break;
}
// Trigger subcategory change, add select menu, etc.
// Here because of the async load for autolevel
if (value !== 'autolevel') {
// reset any autolevel-specific messages while we're here
$('#twinkle-warn-autolevel-message').remove();
Twinkle.warn.callback.postCategoryCleanup(e);
}
};
Twinkle.warn.callback.postCategoryCleanup = function twinklewarnCallbackPostCategoryCleanup(e) {
// clear overridden label on article textbox
Morebits.quickForm.setElementTooltipVisibility(e.target.root.article, true);
Morebits.quickForm.resetElementLabel(e.target.root.article);
// Trigger custom label/change on main category change
Twinkle.warn.callback.change_subcategory(e);
// Use select2 to make the select menu searchable
if (!Twinkle.getPref('oldSelect')) {
$('select[name=sub_group]')
.select2({
width: '100%',
matcher: Morebits.select2.matchers.optgroupFull,
templateResult: Morebits.select2.highlightSearchMatches,
language: {
searching: Morebits.select2.queryInterceptor
}
})
.change(Twinkle.warn.callback.change_subcategory);
$('.select2-selection').keydown(Morebits.select2.autoStart).focus();
mw.util.addCSS(
// Increase height
'.select2-container .select2-dropdown .select2-results > .select2-results__options { max-height: 350px; }' +
// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
'.select2-results .select2-results__group { padding-top: 1px; padding-bottom: 1px; } ' +
// Adjust font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }'
);
}
};
Twinkle.warn.callback.change_subcategory = function twinklewarnCallbackChangeSubcategory(e) {
var main_group = e.target.form.main_group.value;
var value = e.target.form.sub_group.value;
// Tags that don't take a linked article, but something else (often a username).
// The value of each tag is the label next to the input field
var notLinkedArticle = {
'uw-bite': conv({ hans: '被“咬到”的用户(不含User:) ', hant: '被「咬到」的使用者(不含User:) ' }),
'uw-username': conv({ hans: '用户名违反方针,因为… ', hant: '使用者名稱違反方針,因為… ' }),
'uw-aiv': conv({ hans: '可选输入被警告的用户名(不含User:) ', hant: '可選輸入被警告的使用者名稱(不含User:) ' })
};
if (['singlenotice', 'singlewarn', 'singlecombined', 'kitchensink'].indexOf(main_group) !== -1) {
if (notLinkedArticle[value]) {
if (Twinkle.warn.prev_article === null) {
Twinkle.warn.prev_article = e.target.form.article.value;
}
e.target.form.article.notArticle = true;
e.target.form.article.value = '';
// change form labels according to the warning selected
Morebits.quickForm.setElementTooltipVisibility(e.target.form.article, false);
Morebits.quickForm.overrideElementLabel(e.target.form.article, notLinkedArticle[value]);
} else if (e.target.form.article.notArticle) {
if (Twinkle.warn.prev_article !== null) {
e.target.form.article.value = Twinkle.warn.prev_article;
Twinkle.warn.prev_article = null;
}
e.target.form.article.notArticle = false;
Morebits.quickForm.setElementTooltipVisibility(e.target.form.article, true);
Morebits.quickForm.resetElementLabel(e.target.form.article);
}
}
// add big red notice, warning users about how to use {{uw-[coi-]username}} appropriately
$('#tw-warn-red-notice').remove();
var $redWarning;
if (value === 'uw-username') {
$redWarning = $(conv({
hans: "<div style='color: red;' id='tw-warn-red-notice'>{{uw-username}}<b>不应</b>被用于<b>明显</b>违反用户名方针的用户。" +
'明显的违反方针应被报告给UAA。' +
'{{uw-username}}应只被用在边界情况下需要与用户讨论时。</div>',
hant: "<div style='color: red;' id='tw-warn-red-notice'>{{uw-username}}<b>不應</b>被用於<b>明顯</b>違反用戶名方針的用戶。" +
'明顯的違反方針應被報告給UAA。' +
'{{uw-username}}應只被用在邊界情況下需要與用戶討論時。</div>'
}));
$redWarning.insertAfter(Morebits.quickForm.getElementLabelObject(e.target.form.reasonGroup));
}
};
Twinkle.warn.callbacks = {
getWarningWikitext: function(templateName, article, reason, isCustom, noSign) {
var text = '{{subst:' + templateName;
// add linked article for user warnings
if (article) {
text += '|1=' + article;
}
if (reason) {
// add extra message
if (templateName === 'uw-csd') {
text += '|3=' + reason;
} else {
text += '|2=' + reason;
}
}
text += '|subst=subst:}}';
if (!noSign) {
text += ' ~~~~';
}
return text;
},
showPreview: function(form, templatename) {
var input = Morebits.quickForm.getInputData(form);
// Provided on autolevel, not otherwise
templatename = templatename || input.sub_group;
var linkedarticle = input.article;
var templatetext;
templatetext = Twinkle.warn.callbacks.getWarningWikitext(templatename, linkedarticle,
input.reason, input.main_group === 'custom');
form.previewer.beginRender(templatetext, 'User_talk:' + Morebits.wiki.flow.relevantUserName() + (Twinkle.warn.isFlow ? '/Wikitext' : '')); // Force wikitext/correct username
},
// Just a pass-through unless the autolevel option was selected
preview: function(form) {
if (form.main_group.value === 'autolevel') {
// Always get a new, updated talkpage for autolevel processing
var usertalk_page = new Morebits.wiki.page('User_talk:' + Morebits.wiki.flow.relevantUserName(), conv({ hans: '加载上次警告', hant: '載入上次警告' }));
usertalk_page.setFollowRedirect(true, false);
// Will fail silently if the talk page is a cross-ns redirect,
// removal of the preview box handled when loading the menu
usertalk_page.load(function(pageobj) {
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj
var wikitext = pageobj.getPageText();
// history not needed for autolevel
var latest = Twinkle.warn.callbacks.dateProcessing(wikitext)[0];
var params = {
sub_group: form.sub_group.value,
article: form.article.value,
messageData: $(form.sub_group).find('option[value="' + $(form.sub_group).val() + '"]').data('messageData')
};
var template = Twinkle.warn.callbacks.autolevelParseWikitext(wikitext, params, latest)[0];
Twinkle.warn.callbacks.showPreview(form, template);
// If the templates have diverged, fake a change event
// to reload the menu with the updated pageobj
if (form.sub_group.value !== template) {
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
form.main_group.dispatchEvent(evt);
}
});
} else {
Twinkle.warn.callbacks.showPreview(form);
}
},
/**
* Used in the main and autolevel loops to determine when to warn
* about excessively recent, stale, or identical warnings.
* @param {string} wikitext The text of a user's talk page, from getPageText()
* @returns {Object[]} - Array of objects: latest contains most recent
* warning and date; history lists all prior warnings
*/
dateProcessing: function(wikitext) {
var history_re = /<!--\s?Template:([uU]w-.*?)\s?-->.*?(\d{4})年(\d{1,2})月(\d{1,2})日 \([日一二三四五六]\) (\d{1,2}):(\d{1,2}) \(UTC\)/g;
var history = {};
var latest = { date: new Morebits.date(0), type: '' };
var current;
while ((current = history_re.exec(wikitext)) !== null) {
var template = current[1];
var current_date = new Morebits.date(current[2] + '-' + current[3] + '-' + current[4] + ' ' + current[5] + ':' + current[6] + ' UTC');
if (!(template in history) || history[template].isBefore(current_date)) {
history[template] = current_date;
}
if (!latest.date.isAfter(current_date)) {
latest.date = current_date;
latest.type = template;
}
}
return [latest, history];
},
/**
* Main loop for deciding what the level should increment to. Most of
* this is really just error catching and updating the subsequent data.
* May produce up to two notices in a twinkle-warn-autolevel-messages div
*
* @param {string} wikitext The text of a user's talk page, from getPageText() (required)
* @param {Object} params Params object: sub_group is the template (required);
* article is the user-provided article (form.article) used to link ARV on recent level4 warnings;
* messageData is only necessary if getting the full template, as it's
* used to ensure a valid template of that level exists
* @param {Object} latest First element of the array returned from
* dateProcessing. Provided here rather than processed within to avoid
* repeated call to dateProcessing
* @param {(Date|Morebits.date)} date Date from which staleness is determined
* @param {Morebits.status} statelem Status element, only used for handling error in final execution
*
* @returns {Array} - Array that contains the full template and just the warning level
*/
autolevelParseWikitext: function(wikitext, params, latest, date, statelem) {
var level; // undefined rather than '' means the isNaN below will return true
if (/\d(?:im)?$/.test(latest.type)) { // level1-4im
level = parseInt(latest.type.replace(/.*(\d)(?:im)?$/, '$1'), 10);
} else if (latest.type) { // Non-numbered warning
// Try to leverage existing categorization of
// warnings, all but one are universally lowercased
var loweredType = /uw-multipleIPs/i.test(latest.type) ? 'uw-multipleIPs' : latest.type.toLowerCase();
// It would be nice to account for blocks, but in most
// cases the hidden message is terminal, not the sig
if (Twinkle.warn.messages.singlewarn[loweredType]) {
level = 3;
} else {
level = 1; // singlenotice or not found
}
}
var $autolevelMessage = $('<div/>', {id: 'twinkle-warn-autolevel-message'});
if (isNaN(level)) { // No prior warnings found, this is the first
level = 1;
} else if (level > 4 || level < 1) { // Shouldn't happen
var message = conv({ hans: '无法解析上次的警告层级,请手动选择一个警告层级。', hant: '無法解析上次的警告層級,請手動選擇一個警告層級。' });
if (statelem) {
statelem.error(message);
} else {
alert(message);
}
return;
} else {
date = date || new Date();
var autoTimeout = new Morebits.date(latest.date.getTime()).add(parseInt(Twinkle.getPref('autolevelStaleDays'), 10), 'day');
if (autoTimeout.isAfter(date)) {
if (level === 4) {
level = 4;
// Basically indicates whether we're in the final Main evaluation or not,
// and thus whether we can continue or need to display the warning and link
if (!statelem) {
var $link = $('<a/>', {
href: '#',
text: conv({ hans: '单击此处打开告状工具', hant: '點擊此處打開告狀工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.warn.dialog.close();
Twinkle.arv.callback(Morebits.wiki.flow.relevantUserName());
$('input[name=page]').val(params.article); // Target page
$('input[value=final]').prop('checked', true); // Vandalism after final
}
});
var statusNode = $('<div/>', {
text: Morebits.wiki.flow.relevantUserName() + conv({ hans: '最后收到了一个层级4警告(', hant: '最後收到了一個層級4警告(' }) + latest.type + conv({ hans: '),所以将其报告给管理人员会比较好;', hant: '),所以將其報告給管理人員會比較好;' }),
css: {color: 'red' }
});
statusNode.append($link[0]);
$autolevelMessage.append(statusNode);
}
} else { // Automatically increase severity
level += 1;
}
} else { // Reset warning level if most-recent warning is too old
level = 1;
}
}
$autolevelMessage.prepend($('<div>' + conv({ hans: '将发送', hant: '將發送' }) + '<span style="font-weight: bold;">' + conv({ hans: '层级', hant: '層級' }) + level + '</span>' + '警告模板' + '。</div>'));
// Place after the stale and other-user-reverted (text-only) messages
$('#twinkle-warn-autolevel-message').remove(); // clean slate
$autolevelMessage.insertAfter($('#twinkle-warn-warning-messages'));
var template = params.sub_group.replace(/(.*)\d$/, '$1');
// Validate warning level, falling back to the uw-generic series.
// Only a few items are missing a level, and in all but a handful
// of cases, the uw-generic series is explicitly used elsewhere per WP:UTM.
if (params.messageData && !params.messageData['level' + level]) {
template = 'uw-generic';
}
template += level;
return [template, level];
},
main: function(pageobj) {
var text = pageobj.getPageText();
var statelem = pageobj.getStatusElement();
var params = pageobj.getCallbackParameters();
var messageData = params.messageData;
// JS somehow didn't get destructured assignment until ES6 so of course IE doesn't support it
var warningHistory = Twinkle.warn.callbacks.dateProcessing(text);
var latest = warningHistory[0];
var history = warningHistory[1];
var now = new Morebits.date(pageobj.getLoadTime());
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj, just in case
if (params.main_group === 'autolevel') {
// [template, level]
var templateAndLevel = Twinkle.warn.callbacks.autolevelParseWikitext(text, params, latest, now, statelem);
// Only if there's a change from the prior display/load
if (params.sub_group !== templateAndLevel[0] && !confirm(conv({ hans: '将发送给用户{{', hant: '將發送給使用者{{' }) + templateAndLevel[0] + conv({ hans: '}}模板,好吗?', hant: '}}模板,好嗎?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
// Update params now that we've selected a warning
params.sub_group = templateAndLevel[0];
messageData = params.messageData['level' + templateAndLevel[1]];
} else if (params.sub_group in history) {
if (new Morebits.date(history[params.sub_group]).add(1, 'day').isAfter(now)) {
if (!confirm(conv({ hans: '近24小时内一个同样的 ', hant: '近24小時內一個同樣的 ' }) + params.sub_group + conv({ hans: ' 模板已被发出。\n是否继续?', hant: ' 模板已被發出。\n是否繼續?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
}
}
latest.date.add(1, 'minute'); // after long debate, one minute is max
if (latest.date.isAfter(now)) {
if (!confirm(conv({ hans: '近1分钟内 ', hant: '近1分鐘內 ' }) + latest.type + conv({ hans: ' 模板已被发出。\n是否继续?', hant: ' 模板已被發出。\n是否繼續?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
}
// build the edit summary
// Function to handle generation of summary prefix for custom templates
var customProcess = function(template) {
template = template.split('|')[0];
var prefix;
switch (template.substr(-1)) {
case '1':
prefix = '提醒';
break;
case '2':
prefix = '注意';
break;
case '3':
prefix = '警告';
break;
case '4':
prefix = conv({ hans: '最后警告', hant: '最後警告' });
break;
case 'm':
if (template.substr(-3) === '4im') {
prefix = '唯一警告';
break;
}
// falls through
default:
prefix = '提醒';
break;
}
return prefix + ':' + Morebits.string.toUpperCaseFirstChar(messageData.label);
};
var summary;
if (params.main_group === 'custom') {
summary = customProcess(params.sub_group);
} else {
// Normalize kitchensink to the 1-4im style
if (params.main_group === 'kitchensink' && !/^D+$/.test(params.sub_group)) {
var sub = params.sub_group.substr(-1);
if (sub === 'm') {
sub = params.sub_group.substr(-3);
}
// Don't overwrite uw-3rr, technically unnecessary
if (/\d/.test(sub)) {
params.main_group = 'level' + sub;
}
}
// singlet || level1-4im, no need to /^\D+$/.test(params.main_group)
summary = messageData.summary || (messageData[params.main_group] && messageData[params.main_group].summary);
// Not in Twinkle.warn.messages, assume custom template
if (!summary) {
summary = customProcess(params.sub_group);
}
if (messageData.suppressArticleInSummary !== true && params.article) {
if (params.sub_group === 'uw-aiv') { // these templates require a username
summary += '(' + conv({ hans: '对于', hant: '對於' }) + '[[User:' + params.article + ']])';
} else if (params.sub_group === 'uw-bite') { // this template requires a username
summary += ',' + conv({ hans: '于', hant: '於' }) + '[[User talk:' + params.article + ']]';
} else {
summary += conv({ hans: ',于[[', hant: ',於[[' }) + params.article + ']]';
}
}
}
pageobj.setEditSummary(summary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchWarnings'));
// Get actual warning text
var warningText = Twinkle.warn.callbacks.getWarningWikitext(params.sub_group, params.article,
params.reason, params.main_group === 'custom');
if (Twinkle.getPref('showSharedIPNotice') && mw.util.isIPAddress(mw.config.get('wgTitle'))) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入共享IP说明', hant: '加入共享IP說明' }));
warningText += '\n{{subst:SharedIPAdvice}}';
}
var sectionExists = false, sectionNumber = 0;
// Only check sections if there are sections or there's a chance we won't create our own
if (!messageData.heading && text.length) {
// Get all sections
var sections = text.match(/^(==*).+\1/gm);
if (sections && sections.length !== 0) {
// Find the index of the section header in question
var dateHeaderRegex = now.monthHeaderRegex();
sectionNumber = 0;
// Find this month's section among L2 sections, preferring the bottom-most
sectionExists = sections.reverse().some(function(sec, idx) {
return /^(==)[^=].+\1/m.test(sec) && dateHeaderRegex.test(sec) && typeof (sectionNumber = sections.length - 1 - idx) === 'number';
});
}
}
if (sectionExists) { // append to existing section
pageobj.setPageSection(sectionNumber + 1);
pageobj.setAppendText('\n\n' + warningText);
pageobj.append();
} else {
if (messageData.heading) { // create new section
pageobj.setNewSectionTitle(messageData.heading);
} else {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '未找到当月的二级标题,将创建新的', hant: '未找到當月的二級標題,將建立新的' }));
pageobj.setNewSectionTitle(now.monthHeader(0));
}
pageobj.setNewSectionText(warningText);
pageobj.newSection();
}
},
main_flow: function (flowobj) {
var params = flowobj.getCallbackParameters();
var messageData = params.messageData;
// build the edit summary
// Function to handle generation of summary prefix for custom templates
var customProcess = function(template) {
template = template.split('|')[0];
var prefix;
switch (template.substr(-1)) {
case '1':
prefix = '提醒';
break;
case '2':
prefix = '注意';
break;
case '3':
prefix = '警告';
break;
case '4':
prefix = conv({ hans: '最后警告', hant: '最後警告' });
break;
case 'm':
if (template.substr(-3) === '4im') {
prefix = '唯一警告';
break;
}
// falls through
default:
prefix = '提醒';
break;
}
return prefix + ':' + Morebits.string.toUpperCaseFirstChar(messageData.label);
};
var topic;
if (messageData.heading) {
topic = messageData.heading;
} else {
// Normalize kitchensink to the 1-4im style
if (params.main_group === 'kitchensink' && !/^D+$/.test(params.sub_group)) {
var sub = params.sub_group.substr(-1);
if (sub === 'm') {
sub = params.sub_group.substr(-3);
}
// Don't overwrite uw-3rr, technically unnecessary
if (/\d/.test(sub)) {
params.main_group = 'level' + sub;
}
}
// singlet || level1-4im, no need to /^\D+$/.test(params.main_group)
topic = messageData.summary || (messageData[params.main_group] && messageData[params.main_group].summary);
// Not in Twinkle.warn.messages, assume custom template
if (!topic) {
topic = customProcess(params.sub_group);
}
}
var content = Twinkle.warn.callbacks.getWarningWikitext(params.sub_group, params.article,
params.reason, params.main_group === 'custom', true);
flowobj.setTopic(topic);
flowobj.setContent(content);
flowobj.newTopic();
}
};
Twinkle.warn.callback.evaluate = function twinklewarnCallbackEvaluate(e) {
var userTalkPage = 'User_talk:' + Morebits.wiki.flow.relevantUserName();
// reason, main_group, sub_group, article
var params = Morebits.quickForm.getInputData(e.target);
// Check that a reason was filled in if uw-username was selected
if (params.sub_group === 'uw-username' && !params.article) {
alert(conv({ hans: '必须给{{uw-username}}提供理由。', hant: '必須給{{uw-username}}提供理由。' }));
return;
}
if (params.article) {
if (/https?:\/\//.test(params.article)) {
alert(conv({ hans: '“页面链接”不能使用网址。', hant: '「頁面連結」不能使用網址。' }));
return;
}
try {
var article = new mw.Title(params.article);
params.article = article.getPrefixedText();
if (article.getFragment()) {
params.article += '#' + article.getFragment();
}
} catch (error) {
alert(conv({ hans: '“页面链接”不合法,仅能输入一个页面名称,勿使用网址、[[ ]],可使用Special:Diff。', hant: '「頁面連結」不合法,僅能輸入一個頁面名稱,勿使用網址、[[ ]],可使用Special:Diff。' }));
return;
}
}
// The autolevel option will already know by now if a user talk page
// is a cross-namespace redirect (via !!Twinkle.warn.talkpageObj), so
// technically we could alert an error here, but the user will have
// already ignored the bold red error above. Moreover, they probably
// *don't* want to actually issue a warning, so the error handling
// after the form is submitted is probably preferable
// Find the selected <option> element so we can fetch the data structure
var $selectedEl = $(e.target.sub_group).find('option[value="' + $(e.target.sub_group).val() + '"]');
params.messageData = $selectedEl.data('messageData');
if (typeof params.messageData === 'undefined') {
alert(conv({ hans: '请选择警告模板。', hant: '請選擇警告模板。' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '警告完成,将在几秒后刷新', hant: '警告完成,將在幾秒後重新整理' });
if (Twinkle.warn.isFlow) {
var flow_page = new Morebits.wiki.flow(userTalkPage, conv({ hans: '用户Flow讨论页留言', hant: '使用者Flow討論頁留言' }));
flow_page.setCallbackParameters(params);
Twinkle.warn.callbacks.main_flow(flow_page);
} else {
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '用户讨论页修改', hant: '使用者討論頁修改' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setFollowRedirect(true, false);
wikipedia_page.load(Twinkle.warn.callbacks.main);
}
};
Twinkle.addInitCallback(Twinkle.warn, 'warn');
})(jQuery);
// </nowiki>
0a47614bec17c45ab5164d79eb15e23d93ec53c7
MediaWiki:Gadget-friendlytag.js
8
161
324
2023-11-06T13:17:47Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlytag.js: Tag module
****************************************
* Mode of invocation: Tab ("Tag")
* Active on: Existing articles and drafts; file pages with a corresponding file
* which is local (not on Commons); all redirects
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.tag = function friendlytag() {
// redirect tagging
if (Morebits.isPageRedirect()) {
Twinkle.tag.mode = conv({ hans: '重定向', hant: '重新導向' });
Twinkle.tag.modeEn = 'redirect';
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记重定向', hant: '標記重新導向' }));
// file tagging
} else if (mw.config.get('wgNamespaceNumber') === 6 && !document.getElementById('mw-sharedupload') && document.getElementById('mw-imagepage-section-filehistory')) {
Twinkle.tag.mode = conv({ hans: '文件', hant: '檔案' });
Twinkle.tag.modeEn = 'file';
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记文件', hant: '標記檔案' }));
// article/draft tagging
} else if (([0, 118].indexOf(mw.config.get('wgNamespaceNumber')) !== -1 && mw.config.get('wgCurRevisionId')) || (Morebits.pageNameNorm === Twinkle.getPref('sandboxPage'))) {
Twinkle.tag.mode = conv({ hans: '条目', hant: '條目' });
Twinkle.tag.modeEn = 'article';
// Can't remove tags when not viewing current version
Twinkle.tag.canRemove = (mw.config.get('wgCurRevisionId') === mw.config.get('wgRevisionId')) &&
// Disabled on latest diff because the diff slider could be used to slide
// away from the latest diff without causing the script to reload
!mw.config.get('wgDiffNewId');
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记条目', hant: '標記條目' }));
}
};
Twinkle.tag.checkedTags = [];
Twinkle.tag.callback = function friendlytagCallback() {
var Window = new Morebits.simpleWindow(630, Twinkle.tag.modeEn === 'article' ? 500 : 400);
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '标记设置', hant: '標記設定' }), 'WP:TW/PREF#tag');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#tag');
var form = new Morebits.quickForm(Twinkle.tag.callback.evaluate);
form.append({
type: 'input',
label: conv({ hans: '筛选标记列表:', hant: '篩選標記列表:' }),
name: 'quickfilter',
size: '30',
event: function twinkletagquickfilter() {
// flush the DOM of all existing underline spans
$allCheckboxDivs.find('.search-hit').each(function(i, e) {
var label_element = e.parentElement;
// This would convert <label>Hello <span class=search-hit>wo</span>rld</label>
// to <label>Hello world</label>
label_element.innerHTML = label_element.textContent;
});
if (this.value) {
$allCheckboxDivs.hide();
$allHeaders.hide();
var searchString = this.value;
var searchRegex = new RegExp(mw.util.escapeRegExp(searchString), 'i');
$allCheckboxDivs.find('label').each(function () {
var label_text = this.textContent;
var searchHit = searchRegex.exec(label_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
this.parentElement.style.display = 'block'; // show
}
});
} else {
$allCheckboxDivs.show();
$allHeaders.show();
}
}
});
switch (Twinkle.tag.modeEn) {
case 'article':
Window.setTitle(conv({ hans: '条目维护标记', hant: '條目維護標記' }));
// Build sorting and lookup object flatObject, which is always
// needed but also used to generate the alphabetical list
// Would be infinitely better with Object.values, but, alas, IE 11
Twinkle.tag.article.flatObject = {};
Twinkle.tag.article.tagList.forEach(function(group) {
group.value.forEach(function(subgroup) {
if (subgroup.value) {
subgroup.value.forEach(function(item) {
Twinkle.tag.article.flatObject[item.tag] = { description: item.description, excludeMI: !!item.excludeMI };
});
} else {
Twinkle.tag.article.flatObject[subgroup.tag] = { description: subgroup.description, excludeMI: !!subgroup.excludeMI };
}
});
});
form.append({
type: 'select',
name: 'sortorder',
label: conv({ hans: '查看列表:', hant: '檢視列表:' }),
tooltip: conv({ hans: '您可以在Twinkle参数设置(WP:TWPREFS)中更改此项。', hant: '您可以在Twinkle偏好設定(WP:TWPREFS)中更改此項。' }),
event: Twinkle.tag.updateSortOrder,
list: [
{ type: 'option', value: 'cat', label: conv({ hans: '按类型', hant: '按類別' }), selected: Twinkle.getPref('tagArticleSortOrder') === 'cat' },
{ type: 'option', value: 'alpha', label: '按字母', selected: Twinkle.getPref('tagArticleSortOrder') === 'alpha' }
]
});
if (!Twinkle.tag.canRemove) {
var divElement = document.createElement('div');
divElement.innerHTML = conv({ hans: '要移除现有维护标记,请从当前条目版本中打开“标记”菜单', hant: '要移除現有維護標記,請從目前條目版本中打開「標記」選單' });
form.append({
type: 'div',
name: 'untagnotice',
label: divElement
});
}
form.append({
type: 'div',
id: 'tagWorkArea',
className: 'morebits-scrollbox',
style: 'max-height: 28em'
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,合并入{{multiple issues}}', hant: '如可能,合併入{{multiple issues}}' }),
value: 'group',
name: 'group',
tooltip: conv({
hans: '如果加入{{multiple issues}}支持的三个以上的模板,所有支持的模板都会被合并入{{multiple issues}}模板中。',
hant: '如果加入{{multiple issues}}支援的三個以上的模板,所有支援的模板都會被合併入{{multiple issues}}模板中。'
}),
checked: Twinkle.getPref('groupByDefault')
}
]
});
form.append({
type: 'input',
label: '理由:',
name: 'reason',
tooltip: conv({
hans: '附加于编辑摘要的可选理由,例如指出条目内容的哪些部分有问题或移除模板的理由,但如果理由很长则应该发表在讨论页。',
hant: '附加於編輯摘要的可選理由,例如指出條目內容的哪些部分有問題或移除模板的理由,但如果理由很長則應該發表在討論頁。'
}),
size: '80'
});
break;
case 'file':
Window.setTitle(conv({ hans: '文件维护标记', hant: '檔案維護標記' }));
Twinkle.tag.fileList.forEach(function(group) {
if (group.buildFilename) {
group.value.forEach(function(el) {
el.subgroup = {
type: 'input',
label: conv({ hans: '替换的文件:', hant: '替換的檔案:' }),
tooltip: conv({ hans: '输入替换此文件的文件名称(必填)', hant: '輸入替換此檔案的檔案名稱(必填)' }),
name: el.value.replace(/ /g, '_') + 'File'
};
});
}
form.append({ type: 'header', label: group.key });
form.append({ type: 'checkbox', name: 'tags', list: group.value });
});
if (Twinkle.getPref('customFileTagList').length) {
form.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
form.append({ type: 'checkbox', name: 'tags', list: Twinkle.getPref('customFileTagList') });
}
break;
case 'redirect':
Window.setTitle(conv({ hans: '重定向标记', hant: '重新導向標記' }));
var i = 1;
Twinkle.tag.redirectList.forEach(function(group) {
form.append({ type: 'header', id: 'tagHeader' + i, label: group.key });
form.append({
type: 'checkbox',
name: 'tags',
list: group.value.map(function (item) {
return { value: item.tag, label: '{{' + item.tag + '}}:' + item.description, subgroup: item.subgroup };
})
});
});
if (Twinkle.getPref('customRedirectTagList').length) {
form.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
form.append({ type: 'checkbox', name: 'tags', list: Twinkle.getPref('customRedirectTagList') });
}
break;
default:
alert('Twinkle.tag:未知模式 ' + Twinkle.tag.mode);
break;
}
if (document.getElementsByClassName('patrollink').length) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '标记页面为已巡查', hant: '標記頁面為已巡查' }),
value: 'patrol',
name: 'patrol',
checked: Twinkle.getPref('markTaggedPagesAsPatrolled')
}
]
});
}
form.append({ type: 'submit', className: 'tw-tag-submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// for quick filter:
$allCheckboxDivs = $(result).find('[name$=tags]').parent();
$allHeaders = $(result).find('h5');
result.quickfilter.focus(); // place cursor in the quick filter field as soon as window is opened
result.quickfilter.autocomplete = 'off'; // disable browser suggestions
result.quickfilter.addEventListener('keypress', function(e) {
if (e.keyCode === 13) { // prevent enter key from accidentally submitting the form
e.preventDefault();
return false;
}
});
if (Twinkle.tag.modeEn === 'article') {
Twinkle.tag.alreadyPresentTags = [];
if (Twinkle.tag.canRemove) {
// Look for existing maintenance tags in the lead section and put them in array
// All tags are HTML table elements that are direct children of .mw-parser-output,
// except when they are within {{multiple issues}}
$('.mw-parser-output').children().each(function parsehtml(i, e) {
// break out on encountering the first heading, which means we are no
// longer in the lead section
if (e.tagName === 'H2') {
return false;
}
// The ability to remove tags depends on the template's {{ambox}} |name=
// parameter bearing the template's correct name (preferably) or a name that at
// least redirects to the actual name
// All tags have their first class name as "box-" + template name
if (e.className.indexOf('box-') === 0) {
if (e.classList[0] === 'box-问题条目') {
$(e).find('.ambox').each(function(idx, e) {
if (e.classList[0].indexOf('box-') === 0) {
var tag = e.classList[0].slice('box-'.length).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
}
});
return true; // continue
}
var tag = e.classList[0].slice('box-'.length).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
}
});
// {{Uncategorized}} and {{Improve categories}} are usually placed at the end
if ($('.box-Uncategorized').length) {
Twinkle.tag.alreadyPresentTags.push('Uncategorized');
}
if ($('.box-Improve_categories').length) {
Twinkle.tag.alreadyPresentTags.push('Improve categories');
}
}
// Add status text node after Submit button
var statusNode = document.createElement('small');
statusNode.id = 'tw-tag-status';
Twinkle.tag.status = {
// initial state; defined like this because these need to be available for reference
// in the click event handler
numAdded: 0,
numRemoved: 0
};
$('button.tw-tag-submit').after(statusNode);
// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sortorder.dispatchEvent(evt);
} else {
// Redirects and files: Add a link to each template's description page
Morebits.quickForm.getElements(result, 'tags').forEach(generateLinks);
}
};
// $allCheckboxDivs and $allHeaders are defined globally, rather than in the
// quickfilter event function, to avoid having to recompute them on every keydown
var $allCheckboxDivs, $allHeaders;
Twinkle.tag.updateSortOrder = function(e) {
var form = e.target.form;
var sortorder = e.target.value;
Twinkle.tag.checkedTags = form.getChecked('tags');
var container = new Morebits.quickForm.element({ type: 'fragment' });
// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: '{{' + tag + '}}: ' + description };
if (Twinkle.tag.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
switch (tag) {
case 'Expand language':
checkbox.subgroup = [
{
name: 'expandLanguage',
type: 'input',
label: conv({ hans: '外语版本语言代码(必填):', hant: '外語版本語言代碼(必填):' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
},
{
name: 'expandLanguage2',
type: 'input',
label: conv({ hans: '外语版本语言代码:', hant: '外語版本語言代碼:' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle2',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
},
{
name: 'expandLanguage3',
type: 'input',
label: conv({ hans: '外语版本语言代码:', hant: '外語版本語言代碼:' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle3',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
}
];
break;
case 'Expert needed':
checkbox.subgroup = [
{
name: 'expert',
type: 'input',
label: conv({ hans: '哪个领域的专家(必填):', hant: '哪個領域的專家(必填):' }),
tooltip: conv({ hans: '必填,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '必填,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
},
{
name: 'expert2',
type: 'input',
label: conv({ hans: '哪个领域的专家:', hant: '哪個領域的專家:' }),
tooltip: conv({ hans: '可选,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '可選,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
},
{
name: 'expert3',
type: 'input',
label: conv({ hans: '哪个领域的专家:', hant: '哪個領域的專家:' }),
tooltip: conv({ hans: '可选,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '可選,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
}
];
break;
case 'Merge':
case 'Merge from':
case 'Merge to':
var otherTagName = 'Merge';
switch (tag) {
case 'Merge from':
otherTagName = 'Merge to';
break;
case 'Merge to':
otherTagName = 'Merge from';
break;
// no default
}
checkbox.subgroup = [
{
name: 'mergeTarget',
type: 'input',
label: conv({ hans: '其他条目:', hant: '其他條目:' }),
tooltip: conv({ hans: '如指定多个条目,请用管道符分隔:条目甲|条目乙', hant: '如指定多個條目,請用管道符分隔:條目甲|條目乙' })
},
{
type: 'checkbox',
list: [
{
name: 'mergeTagOther',
label: '用{{' + otherTagName + conv({ hans: '}}标记其他条目', hant: '}}標記其他條目' }),
checked: true,
tooltip: conv({ hans: '仅在只输入了一个条目名时可用', hant: '僅在只輸入了一個條目名時可用' })
}
]
}
];
if (mw.config.get('wgNamespaceNumber') === 0) {
checkbox.subgroup.push({
name: 'mergeReason',
type: 'textarea',
label: conv({
hans: '合并理由(会被贴上' + (tag === 'Merge to' ? '其他' : '这') + '条目的讨论页):',
hant: '合併理由(會被貼上' + (tag === 'Merge to' ? '其他' : '這') + '條目的討論頁):'
}),
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。仅在只输入了一个条目名时可用。', hant: '可選,但強烈推薦。如不需要請留空。僅在只輸入了一個條目名時可用。' })
});
}
break;
case 'Missing information':
checkbox.subgroup = {
name: 'missingInformation',
type: 'input',
label: conv({ hans: '缺少的内容(必填):', hant: '缺少的內容(必填):' }),
tooltip: conv({ hans: '必填,显示为“缺少有关……的信息。”', hant: '必填,顯示為「缺少有關……的資訊。」' })
};
break;
case 'Notability':
checkbox.subgroup = {
name: 'notability',
type: 'select',
list: [
{ label: '{{Notability}}:' + conv({ hans: '通用的关注度指引', hant: '通用的關注度指引' }), value: 'none' },
{ label: '{{Notability|Astro}}:' + conv({ hans: '天体', hant: '天體' }), value: 'Astro' },
{ label: '{{Notability|Biographies}}:' + conv({ hans: '人物传记', hant: '人物傳記' }), value: 'Biographies' },
{ label: '{{Notability|Book}}:' + conv({ hans: '书籍', hant: '書籍' }), value: 'Book' },
{ label: '{{Notability|Cyclone}}:' + conv({ hans: '气旋', hant: '氣旋' }), value: 'Cyclone' },
{ label: '{{Notability|Fiction}}:' + conv({ hans: '虚构事物', hant: '虛構事物' }), value: 'Fiction' },
{ label: '{{Notability|Geographic}}:' + conv({ hans: '地理特征', hant: '地理特徵' }), value: 'Geographic' },
{ label: '{{Notability|Geometry}}:' + conv({ hans: '几何图形', hant: '幾何圖形' }), value: 'Geometry' },
{ label: '{{Notability|Invention}}:' + conv({ hans: '发明、研究', hant: '發明、研究' }), value: 'Invention' },
{ label: '{{Notability|Music}}:' + conv({ hans: '音乐', hant: '音樂' }), value: 'Music' },
{ label: '{{Notability|Numbers}}:' + conv({ hans: '数字', hant: '數字' }), value: 'Numbers' },
{ label: '{{Notability|Organizations}}:' + conv({ hans: '组织', hant: '組織' }), value: 'Organizations' },
{ label: '{{Notability|Property}}:' + conv({ hans: '性质表', hant: '性質表' }), value: 'Property' },
{ label: '{{Notability|Traffic}}:' + '交通', value: 'Traffic' },
{ label: '{{Notability|Web}}:' + conv({ hans: '网站、网络内容', hant: '網站、網路內容' }) + '(非正式指引)', value: 'Web' }
]
};
break;
case 'Requested move':
checkbox.subgroup = [
{
name: 'moveTarget',
type: 'input',
label: conv({ hans: '新名称:', hant: '新名稱:' })
},
{
name: 'moveReason',
type: 'textarea',
label: conv({ hans: '移动理由(会被粘贴该条目的讨论页):', hant: '移動理由(會被貼上該條目的討論頁):' }),
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。', hant: '可選,但強烈推薦。如不需要請留空。' })
}
];
break;
case 'Split':
checkbox.subgroup = [
{
name: 'target1',
type: 'input',
label: conv({ hans: '页面名1:', hant: '頁面名1:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
},
{
name: 'target2',
type: 'input',
label: conv({ hans: '页面名2:', hant: '頁面名2:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
},
{
name: 'target3',
type: 'input',
label: conv({ hans: '页面名3:', hant: '頁面名3:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
}
];
break;
case 'Cleanup':
checkbox.subgroup = [
{
name: 'cleanupReason',
type: 'input',
label: '需要清理的理由',
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。', hant: '可選,但強烈推薦。如不需要請留空。' })
}
];
break;
default:
break;
}
return checkbox;
};
var makeCheckboxesForAlreadyPresentTags = function() {
container.append({ type: 'header', id: 'tagHeader0', label: conv({ hans: '已放置的维护标记', hant: '已放置的維護標記' }) });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv0' });
var checkboxes = [];
var unCheckedTags = e.target.form.getUnchecked('existingTags');
Twinkle.tag.alreadyPresentTags.forEach(function(tag) {
var checkbox =
{
value: tag,
label: '{{' + tag + '}}' + (Twinkle.tag.article.flatObject[tag] ? ': ' + Twinkle.tag.article.flatObject[tag].description : ''),
checked: unCheckedTags.indexOf(tag) === -1
};
checkboxes.push(checkbox);
});
subdiv.append({
type: 'checkbox',
name: 'existingTags',
list: checkboxes
});
};
if (sortorder === 'cat') { // categorical sort order
// function to iterate through the tags and create a checkbox for each one
var doCategoryCheckboxes = function(subdiv, subgroup) {
var checkboxes = [];
$.each(subgroup, function(k, item) {
if (Twinkle.tag.alreadyPresentTags.indexOf(item.tag) === -1) {
checkboxes.push(makeCheckbox(item.tag, item.description));
}
});
subdiv.append({
type: 'checkbox',
name: 'tags',
list: checkboxes
});
};
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
}
var i = 1;
// go through each category and sub-category and append lists of checkboxes
Twinkle.tag.article.tagList.forEach(function(group) {
container.append({ type: 'header', id: 'tagHeader' + i, label: group.key });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv' + i++ });
if (group.value[0].tag) {
doCategoryCheckboxes(subdiv, group.value);
} else {
group.value.forEach(function(subgroup) {
subdiv.append({ type: 'div', label: [ Morebits.htmlNode('b', subgroup.key) ] });
doCategoryCheckboxes(subdiv, subgroup.value);
});
}
});
} else { // alphabetical sort order
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
container.append({ type: 'header', id: 'tagHeader1', label: conv({ hans: '可用的维护标记', hant: '可用的維護標記' }) });
}
// Avoid repeatedly resorting
Twinkle.tag.article.alphabeticalList = Twinkle.tag.article.alphabeticalList || Object.keys(Twinkle.tag.article.flatObject).sort();
var checkboxes = [];
Twinkle.tag.article.alphabeticalList.forEach(function(tag) {
if (Twinkle.tag.alreadyPresentTags.indexOf(tag) === -1) {
checkboxes.push(makeCheckbox(tag, Twinkle.tag.article.flatObject[tag].description));
}
});
container.append({
type: 'checkbox',
name: 'tags',
list: checkboxes
});
}
// append any custom tags
if (Twinkle.getPref('customTagList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
container.append({ type: 'checkbox', name: 'tags',
list: Twinkle.getPref('customTagList').map(function(el) {
el.checked = Twinkle.tag.checkedTags.indexOf(el.value) !== -1;
return el;
})
});
}
var $workarea = $(form).find('#tagWorkArea');
var rendered = container.render();
$workarea.empty().append(rendered);
// for quick filter:
$allCheckboxDivs = $workarea.find('[name=tags], [name=existingTags]').parent();
$allHeaders = $workarea.find('h5, .quickformDescription');
form.quickfilter.value = ''; // clear search, because the search results are not preserved over mode change
form.quickfilter.focus();
// style adjustments
$workarea.find('h5').css({ 'font-size': '110%' });
$workarea.find('h5:not(:first-child)').css({ 'margin-top': '1em' });
$workarea.find('div').filter(':has(span.quickformDescription)').css({ 'margin-top': '0.4em' });
Morebits.quickForm.getElements(form, 'existingTags').forEach(generateLinks);
Morebits.quickForm.getElements(form, 'tags').forEach(generateLinks);
// tally tags added/removed, update statusNode text
var statusNode = document.getElementById('tw-tag-status');
$('[name=tags], [name=existingTags]').click(function() {
if (this.name === 'tags') {
Twinkle.tag.status.numAdded += this.checked ? 1 : -1;
} else if (this.name === 'existingTags') {
Twinkle.tag.status.numRemoved += this.checked ? -1 : 1;
}
var firstPart = '加入' + Twinkle.tag.status.numAdded + conv({ hans: '个标记', hant: '個標記' });
var secondPart = '移除' + Twinkle.tag.status.numRemoved + conv({ hans: '个标记', hant: '個標記' });
statusNode.textContent =
(Twinkle.tag.status.numAdded ? ' ' + firstPart : '') +
(Twinkle.tag.status.numRemoved ? (Twinkle.tag.status.numAdded ? ';' : ' ') + secondPart : '');
});
};
/**
* Adds a link to each template's description page
* @param {Morebits.quickForm.element} checkbox associated with the template
*/
var generateLinks = function(checkbox) {
var link = Morebits.htmlNode('a', '>');
link.setAttribute('class', 'tag-template-link');
var tagname = checkbox.values;
link.setAttribute('href', mw.util.getUrl(
(tagname.indexOf(':') === -1 ? 'Template:' : '') +
(tagname.indexOf('|') === -1 ? tagname : tagname.slice(0, tagname.indexOf('|')))
));
link.setAttribute('target', '_blank');
$(checkbox).parent().append(['\u00A0', link]);
};
// Tags for ARTICLES start here
Twinkle.tag.article = {};
// Tags arranged by category; will be used to generate the alphabetical list,
// but tags should be in alphabetical order within the categories
// excludeMI: true indicate a tag that *does not* work inside {{multiple issues}}
// Add new categories with discretion - the list is long enough as is!
Twinkle.tag.article.tagList = [{
key: conv({ hans: '清理和维护模板', hant: '清理和維護模板' }),
value: [{
key: conv({ hans: '常规清理', hant: '常規清理' }),
value: [
{ tag: 'Cleanup', description: conv({ hans: '可能需要进行清理,以符合维基百科的质量标准', hant: '可能需要進行清理,以符合維基百科的質量標準' }) },
{ tag: 'Cleanup rewrite', description: conv({ hans: '不符合维基百科的质量标准,需要完全重写', hant: '不符合維基百科的質量標準,需要完全重寫' }) },
{ tag: 'Cleanup-jargon', description: conv({ hans: '包含过多行话或专业术语,可能需要简化或提出进一步解释', hant: '包含過多行話或專業術語,可能需要簡化或提出進一步解釋' }) },
{ tag: 'Copy edit', description: conv({ hans: '需要编修,以确保文法、用词、语气、格式、标点等使用恰当', hant: '需要編修,以確保文法、用詞、語氣、格式、標點等使用恰當' }) }
]
},
{
key: conv({ hans: '可能多余的内容', hant: '可能多餘的內容' }),
value: [
{ tag: 'Copypaste', description: conv({ hans: '内容可能是从某个来源处拷贝后粘贴', hant: '內容可能是從某個來源處拷貝後貼上' }) },
{ tag: 'External links', description: conv({ hans: '使用外部链接的方式可能不符合维基百科的方针或指引', hant: '使用外部連結的方式可能不符合維基百科的方針或指引' }) },
{ tag: 'Non-free', description: conv({ hans: '可能过多或不当地使用了受著作权保护的文字、图像或多媒体文件', hant: '可能過多或不當地使用了受版權保護的文字、圖像或多媒體檔案' }) }
]
},
{
key: conv({ hans: '结构和导言', hant: '結構和導言' }),
value: [
{ tag: 'Lead too long', description: conv({ hans: '导言部分也许过于冗长', hant: '導言部分也許過於冗長' }) },
{ tag: 'Lead too short', description: conv({ hans: '导言部分也许不足以概括其内容', hant: '導言部分也許不足以概括其內容' }) },
{ tag: 'Very long', description: conv({ hans: '可能过于冗长', hant: '可能過於冗長' }) }
]
},
{
key: conv({ hans: '虚构作品相关清理', hant: '虛構作品相關清理' }),
value: [
{ tag: 'In-universe', description: conv({ hans: '使用小说故事内的观点描述一个虚构事物', hant: '使用小說故事內的觀點描述一個虛構事物' }) },
{ tag: 'Long plot', description: conv({ hans: '可能包含过于详细的剧情摘要', hant: '可能包含過於詳細的劇情摘要' }) }
]
}]
},
{
key: conv({ hans: '常规条目问题', hant: '常規條目問題' }),
value: [{
key: '重要性和知名度',
value: [
{ tag: 'Notability', description: conv({ hans: '可能不符合通用关注度指引', hant: '可能不符合通用關注度指引' }), excludeMI: true }, // has a subgroup with subcategories
{ tag: 'Notability Unreferenced', description: conv({ hans: '可能具备关注度,但需要来源加以彰显', hant: '可能具備關注度,但需要來源加以彰顯' }) }
]
},
{
key: conv({ hans: '写作风格', hant: '寫作風格' }),
value: [
{ tag: 'Advert', description: conv({ hans: '类似广告或宣传性内容', hant: '類似廣告或宣傳性內容' }) },
{ tag: 'Fanpov', description: conv({ hans: '类似爱好者网页', hant: '類似愛好者網頁' }) },
{ tag: 'How-to', description: conv({ hans: '包含指南或教学内容', hant: '包含指南或教學內容' }) },
{ tag: 'Inappropriate person', description: conv({ hans: '使用不适当的第一人称和第二人称', hant: '使用不適當的第一人稱和第二人稱' }) },
{ tag: 'Newsrelease', description: conv({ hans: '阅读起来像是新闻稿及包含过度的宣传性语调', hant: '閱讀起來像是新聞稿及包含過度的宣傳性語調' }) },
{ tag: 'Prose', description: conv({ hans: '使用了日期或时间列表式记述,需要改写为连贯的叙述性文字', hant: '使用了日期或時間列表式記述,需要改寫為連貫的敘述性文字' }) },
{ tag: 'Review', description: conv({ hans: '阅读起来类似评论,需要清理', hant: '閱讀起來類似評論,需要清理' }) },
{ tag: 'Tone', description: conv({ hans: '语调或风格可能不适合百科全书的写作方式', hant: '語調或風格可能不適合百科全書的寫作方式' }) }
]
},
{
key: conv({ hans: '内容', hant: '內容' }),
value: [
{ tag: 'Expand language', description: conv({ hans: '可以根据其他语言版本扩展', hant: '可以根據其他語言版本擴充' }) }, // these three have a subgroup with several options
{ tag: 'Missing information', description: '缺少必要的信息' }, // these three have a subgroup with several options
{ tag: 'Substub', description: conv({ hans: '过于短小', hant: '過於短小' }), excludeMI: true },
{ tag: 'Unencyclopedic', description: conv({ hans: '可能不适合写入百科全书', hant: '可能不適合寫入百科全書' }) }
]
},
{
key: conv({ hans: '信息和细节', hant: '資訊和細節' }),
value: [
{ tag: 'Expert needed', description: conv({ hans: '需要精通或熟悉本主题的专业人士(专家)参与及协助编辑', hant: '需要精通或熟悉本主題的專業人士(專家)參與及協助編輯' }) },
{ tag: 'Overly detailed', description: conv({ hans: '包含太多过度细节内容', hant: '包含太多過度細節內容' }) },
{ tag: 'Trivia', description: conv({ hans: '应避免有陈列杂项、琐碎资料的部分', hant: '應避免有陳列雜項、瑣碎資料的部分' }) }
]
},
{
key: conv({ hans: '时间性', hant: '時間性' }),
value: [
{ tag: 'Current', description: conv({ hans: '记述新闻动态', hant: '記述新聞動態' }), excludeMI: true }, // Works but not intended for use in MI
{ tag: 'Update', description: conv({ hans: '当前条目或章节需要更新', hant: '當前條目或章節需要更新' }) }
]
},
{
key: conv({ hans: '中立、偏见和事实准确性', hant: '中立、偏見和事實準確性' }),
value: [
{ tag: 'Autobiography', description: conv({ hans: '类似一篇自传,或内容主要由条目描述的当事人或组织撰写、编辑', hant: '類似一篇自傳,或內容主要由條目描述的當事人或組織撰寫、編輯' }) },
{ tag: 'COI', description: conv({ hans: '主要贡献者与本条目所宣扬的内容可能存在利益冲突', hant: '主要貢獻者與本條目所宣揚的內容可能存在利益衝突' }) },
{ tag: 'Disputed', description: conv({ hans: '内容疑欠准确,有待查证', hant: '內容疑欠準確,有待查證' }) },
{ tag: 'Globalize', description: conv({ hans: '仅具有一部分地区的信息或观点', hant: '僅具有一部分地區的資訊或觀點' }) },
{ tag: 'Hoax', description: conv({ hans: '真实性被质疑', hant: '真實性被質疑' }) },
{ tag: 'POV', description: conv({ hans: '中立性有争议。内容、语调可能带有明显的个人观点或地方色彩', hant: '中立性有爭議。內容、語調可能帶有明顯的個人觀點或地方色彩' }) },
{ tag: 'Self-contradictory', description: conv({ hans: '内容自相矛盾', hant: '內容自相矛盾' }) },
{ tag: 'Weasel', description: conv({ hans: '语义模棱两可而损及其中立性或准确性', hant: '語意模棱兩可而損及其中立性或準確性' }) }
]
},
{
key: conv({ hans: '可供查证和来源', hant: '可供查證和來源' }),
value: [
{ tag: 'BLPdispute', description: conv({ hans: '可能违反了维基百科关于生者传记的方针', hant: '可能違反了維基百科關於生者傳記的方針' }) },
{ tag: 'BLPsources', description: conv({ hans: '生者传记需要补充更多可供查证的来源', hant: '生者傳記需要補充更多可供查證的來源' }) },
{ tag: 'BLP unsourced', description: conv({ hans: '生者传记没有列出任何参考或来源', hant: '生者傳記沒有列出任何參考或來源' }) },
{ tag: 'Citecheck', description: conv({ hans: '可能包含不适用或被曲解的引用资料,部分内容的准确性无法被证实', hant: '可能包含不適用或被曲解的引用資料,部分內容的準確性無法被證實' }) },
{ tag: 'More footnotes needed', description: conv({ hans: '因为文内引用不足,部分字句的来源仍然不明', hant: '因為文內引用不足,部分字句的來源仍然不明' }) },
{ tag: 'No footnotes', description: conv({ hans: '因为没有内文引用而来源仍然不明', hant: '因為沒有內文引用而來源仍然不明' }) },
{ tag: 'Onesource', description: conv({ hans: '极大或完全地依赖于某个单一的来源', hant: '極大或完全地依賴於某個單一的來源' }) },
{ tag: 'Original research', description: conv({ hans: '可能包含原创研究或未查证内容', hant: '可能包含原創研究或未查證內容' }) },
{ tag: 'Primarysources', description: conv({ hans: '依赖第一手来源', hant: '依賴第一手來源' }) },
{ tag: 'Refimprove', description: conv({ hans: '需要补充更多来源', hant: '需要補充更多來源' }) },
{ tag: 'Unreferenced', description: conv({ hans: '没有列出任何参考或来源', hant: '沒有列出任何參考或來源' }) }
]
}]
},
{
key: conv({ hans: '具体内容问题', hant: '具體內容問題' }),
value: [{
key: conv({ hans: '语言', hant: '語言' }),
value: [
{ tag: 'NotMandarin', description: conv({ hans: '包含过多不是现代标准汉语的内容', hant: '包含過多不是現代標準漢語的內容' }), excludeMI: true },
{ tag: 'Rough translation', description: conv({ hans: '翻译品质不佳', hant: '翻譯品質不佳' }) }
]
},
{
key: conv({ hans: '链接', hant: '連結' }),
value: [
{ tag: 'Dead end', description: conv({ hans: '需要加上内部链接以构筑百科全书的链接网络', hant: '需要加上內部連結以構築百科全書的連結網絡' }) },
{ tag: 'Orphan', description: conv({ hans: '没有或只有很少链入页面', hant: '沒有或只有很少連入頁面' }) },
{ tag: 'Overlinked', description: conv({ hans: '含有过多、重复、或不必要的内部链接', hant: '含有過多、重複、或不必要的內部連結' }) },
{ tag: 'Underlinked', description: conv({ hans: '需要更多内部链接以构筑百科全书的链接网络', hant: '需要更多內部連結以構築百科全書的連結網絡' }) }
]
},
{
key: conv({ hans: '参考技术', hant: '參考技術' }),
value: [
{ tag: 'Citation style', description: conv({ hans: '引用需要进行清理', hant: '引用需要進行清理' }) }
]
},
{
key: conv({ hans: '分类', hant: '分類' }),
value: [
{ tag: 'Improve categories', description: conv({ hans: '需要更多页面分类', hant: '需要更多頁面分類' }), excludeMI: true },
{ tag: 'Uncategorized', description: conv({ hans: '缺少页面分类', hant: '缺少頁面分類' }), excludeMI: true }
]
}]
},
{
key: conv({ hans: '合并、拆分、移动', hant: '合併、拆分、移動' }),
value: [
{ tag: 'Merge from', description: conv({ hans: '建议将页面并入本页面', hant: '建議將頁面併入本頁面' }), excludeMI: true },
{ tag: 'Merge to', description: conv({ hans: '建议将此页面并入页面', hant: '建議將此頁面併入頁面' }), excludeMI: true },
{ tag: 'Merge', description: conv({ hans: '建议此页面与页面合并', hant: '建議此頁面與頁面合併' }), excludeMI: true },
{ tag: 'Requested move', description: conv({ hans: '建议将此页面移动到新名称', hant: '建議將此頁面移動到新名稱' }), excludeMI: true },
{ tag: 'Split', description: conv({ hans: '建议将此页面分割为多个页面', hant: '建議將此頁面分割為多個頁面' }), excludeMI: true }
]
}];
// Tags for REDIRECTS start here
// Not by policy, but the list roughly approximates items with >500
// transclusions from Template:R template index
Twinkle.tag.redirectList = [{
key: '常用模板',
value: [
{ tag: conv({ hans: '合并重定向', hant: '合併重定向' }), description: conv({ hans: '保持页面题名至相应主条目,令页面内容在合并后仍能保存其编辑历史', hant: '保持頁面題名至相應主條目,令頁面內容在合併後仍能儲存其編輯歷史' }) },
{ tag: conv({ hans: '简繁重定向', hant: '簡繁重定向' }), description: conv({ hans: '引导简体至繁体,或繁体至简体', hant: '引導簡體至繁體,或繁體至簡體' }) },
{ tag: conv({ hans: '关注度重定向', hant: '關注度重定向' }), description: conv({ hans: '缺乏关注度的子主题向有关注度的母主题的重定向', hant: '缺乏關注度的子主題向有關注度的母主題的重定向' }) },
{ tag: '模板重定向', description: conv({ hans: '指向模板的重定向页面', hant: '指向模板的重定向頁面' }) },
{ tag: conv({ hans: '别名重定向', hant: '別名重定向' }), description: conv({ hans: '标题的其他名称、笔名、绰号、同义字等', hant: '標題的其他名稱、筆名、綽號、同義字等' }) },
{ tag: conv({ hans: '译名重定向', hant: '譯名重定向' }), description: conv({ hans: '人物、作品等各项事物的其他翻译名称', hant: '人物、作品等各項事物的其他翻譯名稱' }) },
{ tag: conv({ hans: '缩写重定向', hant: '縮寫重定向' }), description: conv({ hans: '标题缩写', hant: '標題縮寫' }) },
{ tag: conv({ hans: '拼写重定向', hant: '拼寫重定向' }), description: conv({ hans: '标题的其他不同拼写', hant: '標題的其他不同拼寫' }) },
{ tag: conv({ hans: '错字重定向', hant: '錯字重定向' }), description: conv({ hans: '纠正标题的常见错误拼写或误植', hant: '糾正標題的常見錯誤拼寫或誤植' }) },
{ tag: conv({ hans: '旧名重定向', hant: '舊名重定向' }), description: conv({ hans: '将事物早前的名称引导至更改后的主题', hant: '將事物早前的名稱引導至更改後的主題' }) },
{ tag: '全名重定向', description: conv({ hans: '标题的完整或更完整名称', hant: '標題的完整或更完整名稱' }) },
{ tag: '短名重定向', description: conv({ hans: '完整标题名称或人物全名的部分、不完整的名称或简称', hant: '完整標題名稱或人物全名的部分、不完整的名稱或簡稱' }) },
{ tag: '姓氏重定向', description: '人物姓氏' },
{ tag: '名字重定向', description: '人物人名' },
{ tag: '本名重定向', description: '人物本名' },
{
tag: '非中文重定向',
description: conv({ hans: '非中文标题', hant: '非中文標題' }),
subgroup: [
{
name: 'altLangFrom',
type: 'input',
label: '本重新導向的語言(可選)',
tooltip: '輸入重新導向名稱所使用語言的ISO 639代碼,例如en代表英語,代碼可參見 Template:ISO_639_name'
}
]
},
{ tag: '日文重定向', description: conv({ hans: '日语名称', hant: '日語名稱' }) }
]
},
{
key: '偶用模板',
value: [
{ tag: '角色重定向', description: conv({ hans: '电视剧、电影、书籍等作品的角色', hant: '電視劇、電影、書籍等作品的角色' }) },
{ tag: conv({ hans: '章节重定向', hant: '章節重定向' }), description: conv({ hans: '导向至较高密度组织的页面', hant: '導向至較高密度組織的頁面' }) },
{ tag: '列表重定向', description: conv({ hans: '导向至低密度的列表', hant: '導向至低密度的列表' }) },
{ tag: '可能性重定向', description: conv({ hans: '导向至当前提供内容更为详尽的目标页面', hant: '導向至當前提供內容更為詳盡的目標頁面' }) },
{ tag: conv({ hans: '关联字重定向', hant: '關聯字重定向' }), description: conv({ hans: '标题名称关联字', hant: '標題名稱關聯字' }) },
{
tag: conv({ hans: '条目请求重定向', hant: '條目請求重定向' }),
description: conv({ hans: '需要独立条目的页面', hant: '需要獨立條目的頁面' }),
subgroup: [
{
name: 'reqArticleLang',
type: 'input',
label: '外語語言代碼:',
tooltip: '使用ISO 639代碼,可參見 Template:ISO_639_name'
},
{
name: 'reqArticleTitle',
type: 'input',
label: '外語頁面名稱:',
size: 60
}
]
},
{ tag: conv({ hans: '快捷方式重定向', hant: '捷徑重定向' }), description: conv({ hans: '维基百科快捷方式', hant: '維基百科快捷方式' }) }
]
},
{
key: conv({ hans: '鲜用模板', hant: '鮮用模板' }),
value: [
{ tag: conv({ hans: '词组重定向', hant: '詞組重定向' }), description: conv({ hans: '将词组/词组/成语指向切题的条目及恰当章节', hant: '將詞組/詞組/成語指向切題的條目及恰當章節' }) },
{ tag: conv({ hans: '消歧义页重定向', hant: '消歧義頁重定向' }), description: conv({ hans: '指向消歧义页', hant: '指向消歧義頁' }) },
{ tag: '域名重定向', description: conv({ hans: '域名', hant: '網域名稱' }) },
{ tag: '年代重定向', description: conv({ hans: '于年份条目导向至年代条目', hant: '於年份條目導向至年代條目' }) },
{ tag: conv({ hans: '用户框模板重定向', hant: '用戶框模板重定向' }), description: conv({ hans: '用户框模板', hant: '用戶框模板' }) },
{ tag: '重定向模板用重定向', description: conv({ hans: '导向至重定向模板', hant: '導向至重定向模板' }) },
{ tag: 'EXIF重定向', description: conv({ hans: 'JPEG图像文件包含EXIF信息', hant: 'JPEG圖檔包含EXIF資訊' }) }
]
}];
// maintenance tags for FILES start here
Twinkle.tag.fileList = [{
key: conv({ hans: '著作权和来源问题标签', hant: '著作權和來源問題標籤' }),
value: [
{
label: '{{Non-free reduce}}:' + conv({ hans: '非低分辨率的合理使用图像(或过长的音频剪辑等)', hant: '非低解析度的合理使用圖像(或過長的音頻剪輯等)' }), value: 'Non-free reduce'
}
]
},
{
key: conv({ hans: '维基共享资源相关标签', hant: '維基共享資源相關標籤' }),
value: [
{
label: '{{Copy to Wikimedia Commons}}:' + conv({ hans: '自由著作权文件应该被移动至维基共享资源', hant: '自由版權檔案應該被移動至維基共享資源' }), value: 'Copy to Wikimedia Commons'
},
{
label: '{{Do not move to Commons}}:' + conv({ hans: '不要移动至维基共享资源', hant: '不要移動至維基共享資源' }),
value: 'Do not move to Commons',
subgroup: {
type: 'input',
name: 'DoNotMoveToCommons_reason',
label: '原因:',
tooltip: conv({ hans: '输入不应该将该图像移动到维基共享资源的原因(必填)。', hant: '輸入不應該將該圖像移動到維基共享資源的原因(必填)。' })
}
},
{
label: '{{Keep local}}:' + conv({ hans: '请求在本地保留维基共享资源的文件副本', hant: '請求在本地保留維基共享資源的檔案副本' }),
value: 'Keep local',
subgroup: [
{
type: 'input',
name: 'keeplocalName',
label: conv({ hans: '共享资源的不同图像名称:', hant: '共享資源的不同圖像名稱:' }),
tooltip: conv({ hans: '输入在共享资源的图像名称(如果不同于本地名称),不包括 File: 前缀', hant: '輸入在共享資源的圖像名稱(如果不同於本地名稱),不包括 File: 字首' })
},
{
type: 'input',
name: 'keeplocalReason',
label: '原因:',
tooltip: conv({ hans: '输入请求在本地保留文件副本的原因(可选):', hant: '輸入請求在本地保留檔案副本的原因(可選):' })
}
]
},
{
label: '{{Now Commons}}:' + conv({ hans: '文件已被复制到维基共享资源(CSD F7)', hant: '檔案已被複製到維基共享資源(CSD F7)' }),
value: 'Now Commons',
subgroup: {
type: 'input',
name: 'nowcommonsName',
label: conv({ hans: '共享资源的不同图像名称:', hant: '共享資源的不同圖像名稱:' }),
tooltip: conv({ hans: '输入在共享资源的图像名称(如果不同于本地名称),不包括 File: 前缀', hant: '輸入在共享資源的圖像名稱(如果不同於本地名稱),不包括 File: 字首' })
}
}
]
},
{
key: conv({ hans: '清理标签', hant: '清理標籤' }),
value: [
{ label: '{{Watermark}}:' + conv({ hans: '图像包含了水印', hant: '圖像包含了浮水印' }), value: 'Watermark' },
{
label: '{{Rename media}}:' + conv({ hans: '文件应该根据文件名称指引被重命名', hant: '檔案應該根據檔案名稱指引被重新命名' }),
value: 'Rename media',
subgroup: [
{
type: 'input',
name: 'renamemediaNewname',
label: conv({ hans: '新名称:', hant: '新名稱:' }),
tooltip: conv({ hans: '输入图像的新名称(可选)', hant: '輸入圖像的新名稱(可選)' })
},
{
type: 'input',
name: 'renamemediaReason',
label: '原因:',
tooltip: conv({ hans: '输入重命名的原因(可选)', hant: '輸入重新命名的原因(可選)' })
}
]
},
{ label: '{{Should be SVG}}:' + conv({ hans: 'PNG、GIF、JPEG文件应该重制成矢量图形', hant: 'PNG、GIF、JPEG檔案應該重製成向量圖形' }), value: 'Should be SVG' }
]
},
{
key: conv({ hans: '文件取代标签', hant: '檔案取代標籤' }),
value: [
{ label: '{{Obsolete}}:' + conv({ hans: '有新版本可用的过时文件', hant: '有新版本可用的過時檔案' }), value: 'Obsolete' },
{ label: '{{Vector version available}}:' + conv({ hans: '有矢量图形可用的非矢量图形文件', hant: '有向量圖形可用的非向量圖形檔案' }), value: 'Vector version available' }
],
buildFilename: true
}];
Twinkle.tag.callbacks = {
article: function articleCallback(pageobj) {
// Remove tags that become superfluous with this action
var pageText = pageobj.getPageText().replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
var params = pageobj.getCallbackParameters();
/**
* Saves the page following the removal of tags if any. The last step.
* Called from removeTags()
*/
var postRemoval = function() {
if (params.tagsToRemove.length) {
// Remove empty {{multiple issues}} if found
pageText = pageText.replace(/\{\{(multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|\s*\}\}\n?/im, '');
// Remove single-element {{multiple issues}} if found
pageText = pageText.replace(/\{\{(?:multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|\s*(\{\{(?:\{\{[^{}]*\}\}|[^{}])+\}\})\s*\}\}/im, '$1');
}
// Build edit summary
var makeSentence = function(array) {
if (array.length < 3) {
return array.join('和');
}
var last = array.pop();
return array.join('、') + '和' + last;
};
var makeTemplateLink = function(tag) {
var text = '{{[[';
// if it is a custom tag with a parameter
if (tag.indexOf('|') !== -1) {
tag = tag.slice(0, tag.indexOf('|'));
}
text += tag.indexOf(':') !== -1 ? tag : 'Template:' + tag + '|' + tag;
return text + ']]}}';
};
var summaryText;
var addedTags = params.tags.map(makeTemplateLink);
var removedTags = params.tagsToRemove.map(makeTemplateLink);
if (addedTags.length) {
summaryText = '加入' + makeSentence(addedTags);
summaryText += removedTags.length ? '並移除' + makeSentence(removedTags) : '';
} else {
summaryText = '移除' + makeSentence(removedTags);
}
summaryText += conv({ hans: '标记', hant: '標記' });
if (params.reason) {
summaryText += ':' + params.reason;
}
// avoid truncated summaries
if (summaryText.length > 499) {
summaryText = summaryText.replace(/\[\[[^|]+\|([^\]]+)\]\]/g, '$1');
}
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save(function() {
// special functions for merge tags
if (params.mergeReason) {
// post the rationale on the talk page (only operates in main namespace)
var talkpage = new Morebits.wiki.page('Talk:' + params.discussArticle, conv({ hans: '将理由贴进讨论页', hant: '將理由貼進討論頁' }));
talkpage.setNewSectionText(params.mergeReason.trim() + ' ~~~~');
talkpage.setNewSectionTitle('请求与[[' + params.nonDiscussArticle + ']]合并');
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setWatchlist(Twinkle.getPref('watchMergeDiscussions'));
talkpage.setCreateOption('recreate');
talkpage.newSection();
}
if (params.mergeTagOther) {
// tag the target page if requested
var otherTagName = 'Merge';
if (params.mergeTag === 'Merge from') {
otherTagName = 'Merge to';
} else if (params.mergeTag === 'Merge to') {
otherTagName = 'Merge from';
}
var newParams = {
tags: [otherTagName],
tagsToRemove: [],
tagsToRemain: [],
mergeTarget: Morebits.pageNameNorm,
discussArticle: params.discussArticle,
talkDiscussionTitle: params.talkDiscussionTitle,
talkDiscussionTitleLinked: params.talkDiscussionTitleLinked
};
var otherpage = new Morebits.wiki.page(params.mergeTarget, conv({ hans: '标记其他页面(', hant: '標記其他頁面(' }) +
params.mergeTarget + ')');
otherpage.setCallbackParameters(newParams);
otherpage.load(Twinkle.tag.callbacks.article);
}
// special functions for requested move tags
if (params.moveReason) {
// post the rationale on the talk page (only operates in main namespace)
var moveTalkpageText = '\n\n{{subst:RM|1=' + params.moveReason.trim();
if (params.moveTarget) {
moveTalkpageText += '|2=' + params.moveTarget;
}
moveTalkpageText += '}}';
var moveTalkpage = new Morebits.wiki.page('Talk:' + params.discussArticle, conv({ hans: '将理由贴进讨论页', hant: '將理由貼進討論頁' }));
moveTalkpage.setAppendText(moveTalkpageText);
moveTalkpage.setEditSummary(conv({ hans: '请求移动', hant: '請求移動' }) + (params.moveTarget ? '至[[' + params.moveTarget + ']]' : ''));
moveTalkpage.setChangeTags(Twinkle.changeTags);
moveTalkpage.setCreateOption('recreate');
moveTalkpage.append();
}
});
if (params.patrol) {
pageobj.patrol();
}
};
/**
* Removes the existing tags that were deselected (if any)
* Calls postRemoval() when done
*/
var removeTags = function removeTags() {
if (params.tagsToRemove.length === 0) {
postRemoval();
return;
}
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '移除取消选择的已存在标记', hant: '移除取消選擇的已存在標記' }));
var getRedirectsFor = [];
// Remove the tags from the page text, if found in its proper name,
// otherwise moves it to `getRedirectsFor` array earmarking it for
// later removal
params.tagsToRemove.forEach(function removeTag(tag) {
var tag_re = new RegExp('\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]+)?\\}\\}\\n?');
if (tag_re.test(pageText)) {
pageText = pageText.replace(tag_re, '');
} else {
getRedirectsFor.push('Template:' + tag);
}
});
if (!getRedirectsFor.length) {
postRemoval();
return;
}
// Remove tags which appear in page text as redirects
var api = new Morebits.wiki.api(conv({ hans: '获取模板重定向', hant: '取得模板重新導向' }), {
action: 'query',
prop: 'linkshere',
titles: getRedirectsFor.join('|'),
redirects: 1, // follow redirect if the class name turns out to be a redirect page
lhnamespace: '10', // template namespace only
lhshow: 'redirect',
lhlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
}, function removeRedirectTag(apiobj) {
$(apiobj.responseXML).find('page').each(function(idx, page) {
var removed = false;
$(page).find('lh').each(function(idx, el) {
var tag = $(el).attr('title').slice(9);
var tag_re = new RegExp('\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?\\}\\}\\n?');
if (tag_re.test(pageText)) {
pageText = pageText.replace(tag_re, '');
removed = true;
return false; // break out of $.each
}
});
if (!removed) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法在页面上找到{{', hant: '無法在頁面上找到{{' }) + $(page).attr('title').slice(9) + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
});
postRemoval();
});
api.post();
};
if (!params.tags.length) {
removeTags();
return;
}
var tagRe, tagText = '', tags = [], groupableTags = [], groupableExistingTags = [];
// Executes first: addition of selected tags
/**
* Updates `tagText` with the syntax of `tagName` template with its parameters
* @param {number} tagIndex
* @param {string} tagName
*/
var addTag = function articleAddTag(tagIndex, tagName) {
var currentTag = '';
if (tagName === 'Uncategorized' || tagName === 'Improve categories') {
pageText += '\n\n{{' + tagName + '|time={{subst:#time:c}}}}';
} else {
currentTag += '{{' + tagName;
// fill in other parameters, based on the tag
switch (tagName) {
case 'Expand language':
currentTag += '|1=' + params.expandLanguage;
if (params.highQualityArticle) {
currentTag += '|status=yes';
}
if (params.expandLanguage2) {
currentTag += '|2=' + params.expandLanguage2;
if (params.highQualityArticle2) {
currentTag += '|status2=yes';
}
}
if (params.expandLanguage3) {
currentTag += '|3=' + params.expandLanguage3;
if (params.highQualityArticle3) {
currentTag += '|status3=yes';
}
}
break;
case 'Expert needed':
currentTag += '|subject=' + params.expert;
if (params.expert2) {
currentTag += '|subject2=' + params.expert2;
}
if (params.expert3) {
currentTag += '|subject3=' + params.expert3;
}
break;
case 'Merge':
case 'Merge to':
case 'Merge from':
if (params.mergeTarget) {
// normalize the merge target for now and later
params.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.mergeTarget.replace(/_/g, ' '));
currentTag += '|' + params.mergeTarget;
// link to the correct section on the talk page, for article space only
if (mw.config.get('wgNamespaceNumber') === 0 && (params.mergeReason || params.discussArticle)) {
if (!params.discussArticle) {
// discussArticle is the article whose talk page will contain the discussion
params.discussArticle = tagName === 'Merge to' ? params.mergeTarget : mw.config.get('wgTitle');
// nonDiscussArticle is the article which won't have the discussion
params.nonDiscussArticle = tagName === 'Merge to' ? mw.config.get('wgTitle') : params.mergeTarget;
params.talkDiscussionTitle = conv({ hans: '请求与', hant: '請求與' }) + params.nonDiscussArticle + conv({ hans: '合并', hant: '合併' });
}
currentTag += '|discuss=Talk:' + params.discussArticle + '#' + params.talkDiscussionTitle;
}
}
break;
case 'Missing information':
currentTag += '|1=' + params.missingInformation;
break;
case 'Notability':
if (params.notability !== 'none') {
currentTag += '|3=' + params.notability;
}
break;
case 'Requested move':
if (params.moveTarget) {
// normalize the move target for now and later
params.moveTarget = Morebits.string.toUpperCaseFirstChar(params.moveTarget.replace(/_/g, ' '));
params.discussArticle = mw.config.get('wgTitle');
currentTag += '|' + params.moveTarget;
}
break;
case 'Split':
if (params.target1) {
currentTag += '|1=' + params.target1;
}
if (params.target2) {
currentTag += '|2=' + params.target2;
}
if (params.target3) {
currentTag += '|3=' + params.target3;
}
break;
case 'Cleanup':
if (params.cleanupReason) {
currentTag += '|reason=' + params.cleanupReason;
}
break;
default:
break;
}
currentTag += '|time={{subst:#time:c}}}}\n';
tagText += currentTag;
}
};
/**
* Adds the tags which go outside {{multiple issues}}, either because
* these tags aren't supported in {{multiple issues}} or because
* {{multiple issues}} is not being added to the page at all
*/
var addUngroupedTags = function() {
$.each(tags, addTag);
// Insert tag after short description or any hatnotes,
// as well as deletion/protection-related templates
var wikipage = new Morebits.wikitext.page(pageText);
var templatesAfter = Twinkle.hatnoteRegex +
// Protection templates
'pp|pp-.*?|' +
// CSD
'(?:Delete|Db-reason|D|Deletebecause|Db|速删|速刪|Speedy|SD|快删|快刪|CSD)|' +
// AfD
'[rsaiftcmv]fd|vfd-(?:b|q|s|source|v|wikt)|(?:移动到维基|移動到維基)(?:教科书|教科書|语录|語錄|文库|文庫|导游|導遊|词典|詞典)';
pageText = wikipage.insertAfterTemplates(tagText, templatesAfter).getText();
removeTags();
};
// Separate tags into groupable ones (`groupableTags`) and non-groupable ones (`tags`)
params.tags.forEach(function(tag) {
tagRe = new RegExp('\\{\\{' + tag + '(\\||\\}\\})', 'im');
// regex check for preexistence of tag can be skipped if in canRemove mode
if (Twinkle.tag.canRemove || !tagRe.exec(pageText)) {
if (tag === 'Notability' && (mw.config.get('wgNamespaceNumber') === 0 || confirm(conv({ hans: '该页面不是条目,您仍要提报到关注度提报吗?', hant: '該頁面不是條目,您仍要提報到關注度提報嗎?' })))) {
var wikipedia_page = new Morebits.wiki.page('Wikipedia:关注度/提报', conv({ hans: '加入关注度记录项', hant: '加入關注度記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.tag.callbacks.notabilityList);
}
// condition Twinkle.tag.article.tags[tag] to ensure that its not a custom tag
// Custom tags are assumed non-groupable, since we don't know whether MI template supports them
if (Twinkle.tag.article.flatObject[tag] && !Twinkle.tag.article.flatObject[tag].excludeMI) {
groupableTags.push(tag);
} else {
tags.push(tag);
}
} else {
if (tag === 'Merge from') {
tags.push(tag);
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '在页面上找到{{', hant: '在頁面上找到{{' }) + tag + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
// don't do anything else with merge tags
if (['Merge', 'Merge to'].indexOf(tag) !== -1) {
params.mergeTarget = params.mergeReason = params.mergeTagOther = null;
}
}
}
});
// To-be-retained existing tags that are groupable
params.tagsToRemain.forEach(function(tag) {
// If the tag is unknown to us, we consider it non-groupable
if (Twinkle.tag.article.flatObject[tag] && !Twinkle.tag.article.flatObject[tag].excludeMI) {
groupableExistingTags.push(tag);
}
});
var miTest = /\{\{(multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|[^}]+\{/im.exec(pageText);
if (miTest && groupableTags.length > 0) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入支持的标记入已存在的{{multiple issues}}', hant: '加入支援的標記入已存在的{{multiple issues}}' }));
tagText = '';
$.each(groupableTags, addTag);
var miRegex = new RegExp('(\\{\\{\\s*' + miTest[1] + '\\s*(?:\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?)\\}\\}\\s*', 'im');
pageText = pageText.replace(miRegex, '$1' + tagText + '}}\n');
tagText = '';
addUngroupedTags();
} else if (params.group && !miTest && (groupableExistingTags.length + groupableTags.length) >= 2) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入支持的标记入{{multiple issues}}', hant: '加入支援的標記入{{multiple issues}}' }));
tagText += '{{Multiple issues|\n';
/**
* Adds newly added tags to MI
*/
var addNewTagsToMI = function() {
$.each(groupableTags, addTag);
tagText += '}}\n';
addUngroupedTags();
};
var getRedirectsFor = [];
// Reposition the tags on the page into {{multiple issues}}, if found with its
// proper name, else moves it to `getRedirectsFor` array to be handled later
groupableExistingTags.forEach(function repositionTagIntoMI(tag) {
var tag_re = new RegExp('(\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]+)?\\}\\}\\n?)');
if (tag_re.test(pageText)) {
tagText += tag_re.exec(pageText)[1];
pageText = pageText.replace(tag_re, '');
} else {
getRedirectsFor.push('Template:' + tag);
}
});
if (!getRedirectsFor.length) {
addNewTagsToMI();
return;
}
var api = new Morebits.wiki.api(conv({ hans: '获取模板重定向', hant: '取得模板重新導向' }), {
action: 'query',
prop: 'linkshere',
titles: getRedirectsFor.join('|'),
redirects: 1,
lhnamespace: '10', // template namespace only
lhshow: 'redirect',
lhlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
}, function replaceRedirectTag(apiobj) {
$(apiobj.responseXML).find('page').each(function(idx, page) {
var found = false;
$(page).find('lh').each(function(idx, el) {
var tag = $(el).attr('title').slice(9);
var tag_re = new RegExp('(\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]*)?\\}\\}\\n?)');
if (tag_re.test(pageText)) {
tagText += tag_re.exec(pageText)[1];
pageText = pageText.replace(tag_re, '');
found = true;
return false; // break out of $.each
}
});
if (!found) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法在页面上找到{{', hant: '無法在頁面上找到{{' }) + $(page).attr('title').slice(9) + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
});
addNewTagsToMI();
});
api.post();
} else {
tags = tags.concat(groupableTags);
addUngroupedTags();
}
},
notabilityList: function(pageobj) {
// var text = pageobj.getPageText();
// var params = pageobj.getCallbackParameters();
pageobj.setAppendText('\n{{subst:Fameitem|title=' + Morebits.pageNameNorm + '}}');
pageobj.setEditSummary('加入' + '[[' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
},
redirect: function redirect(pageobj) {
var params = pageobj.getCallbackParameters(),
pageText = pageobj.getPageText(),
tagRe, tagText = '', summaryText = '加入',
tags = [], i;
for (i = 0; i < params.tags.length; i++) {
tagRe = new RegExp('(\\{\\{' + params.tags[i] + '(\\||\\}\\}))', 'im');
if (!tagRe.exec(pageText)) {
tags.push(params.tags[i]);
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '在重定向上找到{{', hant: '在重新導向上找到{{' }) + params.tags[i] + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
}
var addTag = function redirectAddTag(tagIndex, tagName) {
tagText += '\n{{' + tagName;
if (tagName === '非中文重定向') {
if (params.altLangFrom) {
tagText += '|1=' + params.altLangFrom;
}
} else if (tagName === '条目请求重定向' || tagName === '條目請求重定向') {
if (params.reqArticleLang && params.reqArticleTitle) {
tagText += '|1=' + params.reqArticleLang;
tagText += '|2=' + params.reqArticleTitle;
}
}
tagText += '}}';
if (tagIndex > 0) {
if (tagIndex === (tags.length - 1)) {
summaryText += '和';
} else if (tagIndex < (tags.length - 1)) {
summaryText += '、';
}
}
summaryText += '{{[[:' + (tagName.indexOf(':') !== -1 ? tagName : 'Template:' + tagName + '|' + tagName) + ']]}}';
};
if (!tags.length) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '没有标签可供标记', hant: '沒有標籤可供標記' }));
}
tags.sort();
$.each(tags, addTag);
// Check for all Rcat shell redirects (from #433)
if (pageText.match(/{{(?:redr|this is a redirect|r(?:edirect)?(?:.?cat.*)?[ _]?sh)/i)) {
// Regex inspired by [[User:Kephir/gadgets/sagittarius.js]] ([[Special:PermaLink/831402893]])
var oldTags = pageText.match(/(\s*{{[A-Za-z\s]+\|(?:\s*1=)?)((?:[^|{}]|{{[^}]+}})+)(}})\s*/i);
pageText = pageText.replace(oldTags[0], oldTags[1] + tagText + oldTags[2] + oldTags[3]);
} else {
// Fold any pre-existing Rcats into taglist and under Rcatshell
var pageTags = pageText.match(/\s*{{.+?重定向.*?}}/img);
var oldPageTags = '';
if (pageTags) {
pageTags.forEach(function(pageTag) {
var pageRe = new RegExp(Morebits.string.escapeRegExp(pageTag), 'img');
pageText = pageText.replace(pageRe, '');
pageTag = pageTag.trim();
oldPageTags += '\n' + pageTag;
});
}
pageText += '\n{{Redirect category shell|' + tagText + oldPageTags + '\n}}';
}
summaryText += (tags.length > 0 ? conv({ hans: '标记', hant: '標記' }) : '{{Redirect category shell}}') + conv({ hans: '到重定向', hant: '到重新導向' });
// avoid truncated summaries
if (summaryText.length > 499) {
summaryText = summaryText.replace(/\[\[[^|]+\|([^\]]+)\]\]/g, '$1');
}
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
},
file: function friendlytagCallbacksFile(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var summary = '加入';
// Add maintenance tags
if (params.tags.length) {
var tagtext = '', currentTag;
$.each(params.tags, function(k, tag) {
// when other commons-related tags are placed, remove "move to Commons" tag
if (['Keep local', 'Now Commons', 'Do not move to Commons'].indexOf(tag) !== -1) {
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
if (tag === 'Vector version available') {
text = text.replace(/\{\{((convert to |convertto|should be |shouldbe|to)?svg|badpng|vectorize)[^}]*\}\}/gi, '');
}
currentTag = tag;
switch (tag) {
case 'Now Commons':
currentTag = 'subst:' + currentTag; // subst
if (params.nowcommonsName !== '') {
currentTag += '|1=' + params.nowcommonsName;
}
break;
case 'Keep local':
if (params.keeplocalName !== '') {
currentTag += '|1=' + params.keeplocalName;
}
if (params.keeplocalReason !== '') {
currentTag += '|reason=' + params.keeplocalReason;
}
break;
case 'Rename media':
if (params.renamemediaNewname !== '') {
currentTag += '|1=' + params.renamemediaNewname;
}
if (params.renamemediaReason !== '') {
currentTag += '|2=' + params.renamemediaReason;
}
break;
case 'Vector version available':
/* falls through */
case 'Obsolete':
currentTag += '|1=' + params[tag.replace(/ /g, '_') + 'File'];
break;
case 'Do not move to Commons':
currentTag += '|reason=' + params.DoNotMoveToCommons_reason;
break;
case 'Copy to Wikimedia Commons':
currentTag += '|human=' + mw.config.get('wgUserName');
break;
default:
break; // don't care
}
currentTag = '{{' + currentTag + '}}\n';
tagtext += currentTag;
summary += '{{' + tag + '}}、';
});
if (!tagtext) {
pageobj.getStatusElement().warn(conv({ hans: '用户取消操作,没什么要做的', hant: '使用者取消操作,沒什麼要做的' }));
return;
}
text = tagtext + text;
}
pageobj.setPageText(text);
pageobj.setEditSummary(summary.substring(0, summary.length - 1));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
}
};
Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
var form = e.target;
var params = Morebits.quickForm.getInputData(form);
// Validation
// Given an array of incompatible tags, check if we have two or more selected
var checkIncompatible = function(conflicts, extra) {
var count = conflicts.reduce(function(sum, tag) {
return sum += params.tags.indexOf(tag) !== -1;
}, 0);
if (count > 1) {
var message = conv({ hans: '请在以下标签中择一使用', hant: '請在以下標籤中擇一使用' }) + ':{{' + conflicts.join('}}、{{') + '}}。';
message += extra ? extra : '';
alert(message);
return true;
}
};
// Given a tag, ensure an associate parameter is present
// Maybe just sock this away in each function???
var checkParameter = function(tag, parameter, description) {
description = description || '理由';
if (params.tags.indexOf(tag) !== -1 && params[parameter].trim() === '') {
alert(conv({ hans: '您必须指定', hant: '您必須指定' }) + '{{' + tag + '}}的' + description + '。');
return true;
}
};
// We could theoretically put them all checkIncompatible calls in a
// forEach loop, but it's probably clearer not to have [[array one],
// [array two]] devoid of context. Likewise, all the checkParameter
// calls could be in one if, but could be similarly confusing.
switch (Twinkle.tag.modeEn) {
case 'article':
params.tagsToRemove = form.getUnchecked('existingTags'); // not in `input`
params.tagsToRemain = params.existingTags || []; // container not created if none present
if ((params.tags.indexOf('Merge') !== -1) || (params.tags.indexOf('Merge from') !== -1) ||
(params.tags.indexOf('Merge to') !== -1)) {
if (checkIncompatible(['Merge', 'Merge from', 'Merge to'], conv({ hans: '如果需要多次合并,请使用{{Merge}}并用管道符分隔条目名(但在这种情形中Twinkle不能自动标记其他条目)。', hant: '如果需要多次合併,請使用{{Merge}}並用管道符分隔條目名(但在這種情形中Twinkle不能自動標記其他條目)。' }))) {
return;
}
if (!params.mergeTarget) {
alert(conv({ hans: '请指定使用于merge模板中的另一个页面标题。', hant: '請指定使用於merge模板中的另一個頁面標題。' }));
return;
}
if ((params.mergeTagOther || params.mergeReason) && params.mergeTarget.indexOf('|') !== -1) {
alert(conv({ hans: '当前还不支持在一次合并中标记多个条目,与开启关于多个条目的讨论。请不要勾选“标记其他条目”并清空“理由”框后再提交。', hant: '目前還不支援在一次合併中標記多個條目,與開啟關於多個條目的討論。請不要勾選「標記其他條目」並清空「理由」框後再提交。' }));
return;
}
}
if (checkParameter('Expand language', 'expandLanguage', conv({ hans: '语言代码', hant: '語言代碼' }))) {
return;
}
if (checkParameter('Missing information', 'missingInformation', conv({ hans: '缺少的内容', hant: '缺少的內容' }))) {
return;
}
if (checkParameter('Expert needed', 'expert', conv({ hans: '专家领域', hant: '專家領域' }))) {
return;
}
break;
case 'file':
// Silly to provide the same string to each of these
if (checkParameter('Obsolete', 'ObsoleteFile', conv({ hans: '替换的文件名称', hant: '替換的檔案名稱' })) ||
checkParameter('Vector version available', 'Vector_version_availableFile', conv({ hans: '替换的文件名称', hant: '替換的檔案名稱' }))) {
return;
}
if (checkParameter('Do not move to Commons', 'DoNotMoveToCommons_reason')) {
return;
}
break;
case 'redirect':
break;
default:
alert('Twinkle.tag:未知模式 ' + Twinkle.tag.mode);
break;
}
// File/redirect: return if no tags selected
// Article: return if no tag is selected and no already present tag is deselected
if (params.tags.length === 0 && (Twinkle.tag.modeEn !== 'article' || params.tagsToRemove.length === 0)) {
alert(conv({ hans: '必须选择至少一个标记!', hant: '必須選擇至少一個標記!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = Morebits.pageNameNorm;
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成,将在几秒内刷新页面', hant: '標記完成,將在幾秒內重新整理頁面' });
if (Twinkle.tag.modeEn === 'redirect') {
Morebits.wiki.actionCompleted.followRedirect = false;
}
var wikipedia_page = new Morebits.wiki.page(Morebits.pageNameNorm, conv({ hans: '正在标记', hant: '正在標記' }) + Twinkle.tag.mode);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.tag.callbacks[Twinkle.tag.modeEn]);
};
Twinkle.addInitCallback(Twinkle.tag, 'tag');
})(jQuery);
// </nowiki>
c72718af4d8d95c5dac3dd4282fe12815ffb78e3
MediaWiki:Gadget-friendlytalkback.js
8
155
312
2023-11-06T13:17:49Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlytalkback.js: Talkback module
****************************************
* Mode of invocation: Tab ("TB")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
* Config directives in: FriendlyConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.talkback = function() {
if (!Morebits.wiki.flow.relevantUserName()) {
return;
}
Twinkle.addPortletLink(Twinkle.talkback.callback, '通告', 'friendly-talkback', conv({ hans: '回复通告', hant: '回覆通告' }));
};
Twinkle.talkback.callback = function() {
if (Morebits.wiki.flow.relevantUserName() === mw.config.get('wgUserName') && !confirm(conv({ hans: '您寂寞到了要自己通告自己的程度么?', hant: '您寂寞到了要自己通告自己的程度麼?' }))) {
return;
}
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '回复通告', hant: '回覆通告' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '关于{{talkback}}', hant: '關於{{talkback}}' }), 'Template:Talkback');
Window.addFooterLink(conv({ hans: '通告设置', hant: '通告設定' }), 'WP:TW/PREF#talkback');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#talkback');
var form = new Morebits.quickForm(Twinkle.talkback.evaluate);
form.append({ type: 'radio', name: 'tbtarget',
list: [
{
label: conv({ hans: '回复:我的讨论页', hant: '回覆:我的討論頁' }),
value: 'mytalk',
checked: 'true'
},
{
label: conv({ hans: '回复:其他用户的讨论页', hant: '回覆:其他使用者的討論頁' }),
value: 'usertalk'
},
{
label: conv({ hans: '回复:其它页面', hant: '回覆:其它頁面' }),
value: 'other'
},
{
label: conv({ hans: '邀请讨论', hant: '邀請討論' }),
value: 'see'
},
{
label: '通告板通知',
value: 'notice'
},
{
label: conv({ hans: '“有新邮件”', hant: '「有新郵件」' }),
value: 'mail'
}
],
event: Twinkle.talkback.changeTarget
});
form.append({
type: 'field',
label: '工作区',
name: 'work_area'
});
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.talkback.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
form.append({ type: 'div', id: 'talkbackpreview', label: [ previewlink ] });
form.append({ type: 'div', id: 'friendlytalkback-previewbox', style: 'display: none' });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
result.previewer = new Morebits.wiki.preview($(result).find('div#friendlytalkback-previewbox').last()[0]);
// We must init the
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.tbtarget[0].dispatchEvent(evt);
// Check whether the user has opted out from talkback
var query = {
action: 'query',
prop: 'extlinks',
titles: 'User talk:' + Morebits.wiki.flow.relevantUserName(),
elquery: 'userjs.invalid/noTalkback',
ellimit: '1'
};
var wpapi = new Morebits.wiki.api(conv({ hans: '抓取退出通告信息', hant: '抓取退出通告資訊' }), query, Twinkle.talkback.callback.optoutStatus);
wpapi.post();
};
Twinkle.talkback.optout = '';
Twinkle.talkback.callback.optoutStatus = function(apiobj) {
var $el = $(apiobj.getXML()).find('el');
if ($el.length) {
Twinkle.talkback.optout = Morebits.wiki.flow.relevantUserName() + conv({ hans: '不希望收到回复通告', hant: '不希望收到回覆通告' });
var url = $el.text();
var reason = mw.util.getParamValue('reason', url);
Twinkle.talkback.optout += reason ? ':' + Morebits.string.appendPunctuation(reason) : '。';
}
$('#twinkle-talkback-optout-message').text(Twinkle.talkback.optout);
};
var prev_page = '';
var prev_section = '';
var prev_message = '';
Twinkle.talkback.changeTarget = function(e) {
var value = e.target.values;
var root = e.target.form;
var old_area = Morebits.quickForm.getElements(root, 'work_area')[0];
if (root.section) {
prev_section = root.section.value;
}
if (root.message) {
prev_message = root.message.value;
}
if (root.page) {
prev_page = root.page.value;
}
var work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '回复通告信息', hant: '回覆通告資訊' }),
name: 'work_area'
});
root.previewer.closePreview();
switch (value) {
case 'mytalk':
/* falls through */
default:
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'usertalk':
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '用户(必填)', hant: '使用者(必填)' }),
tooltip: conv({ hans: '您留言页面的用户名,必填。', hant: '您留言頁面的使用者名稱,必填。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'notice':
var noticeboard = work_area.append({
type: 'select',
name: 'noticeboard',
label: '通告板:'
});
$.each(Twinkle.talkback.noticeboards, function(value, data) {
noticeboard.append({
type: 'option',
label: data.label,
value: value,
selected: !!data.defaultSelected
});
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '章节标题,留空则不会产生章节链接。', hant: '章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'other':
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '完整页面名', hant: '完整頁面名' }),
tooltip: conv({ hans: '您留下消息的完整页面名,比如“Wikipedia talk:Twinkle”。', hant: '您留下訊息的完整頁面名,比如「Wikipedia talk:Twinkle」。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'mail':
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '电子邮件主题(可选)', hant: '電子郵件主題(可選)' }),
tooltip: conv({ hans: '您发出的电子邮件的主题。', hant: '您發出的電子郵件的主題。' })
});
break;
case 'see':
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '完整页面名', hant: '完整頁面名' }),
tooltip: conv({ hans: '您留下消息的完整页面名,比如“Wikipedia talk:Twinkle”。', hant: '您留下訊息的完整頁面名,比如「Wikipedia talk:Twinkle」。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
}
if (value !== 'notice') {
work_area.append({ type: 'textarea', label: conv({ hans: '附加信息(可选):', hant: '附加資訊(可選):' }), name: 'message', tooltip: conv({ hans: '会在回复通告模板下出现的消息,您的签名会被加在最后。', hant: '會在回覆通告模板下出現的訊息,您的簽名會被加在最後。' }) });
}
work_area = work_area.render();
root.replaceChild(work_area, old_area);
if (root.message) {
root.message.value = prev_message;
}
$('#twinkle-talkback-optout-message').text(Twinkle.talkback.optout);
};
Twinkle.talkback.noticeboards = {
affp: {
label: 'WP:AF/FP(' + conv({ hans: '防滥用过滤器/错误报告', hant: '防濫用過濾器/錯誤報告' }) + ')',
title: conv({ hans: '过滤器错误报告有新回应', hant: '過濾器錯誤報告有新回應' }),
content: conv({ hans: '您的[[Wikipedia:防滥用过滤器/错误报告|过滤器错误报告]]已有回应,请前往查看。', hant: '您的[[Wikipedia:防滥用过滤器/错误报告|過濾器錯誤報告]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[Wikipedia:防滥用过滤器/错误报告]]的通知', hant: '有關[[Wikipedia:防滥用过滤器/错误报告]]的通知' }),
defaultSelected: true
},
sbl: {
label: 'Spam-blacklist',
title: conv({ hans: '垃圾链接黑名单请求有新回应', hant: '垃圾連結黑名單請求有新回應' }),
content: conv({ hans: '您的[[MediaWiki talk:Spam-blacklist|垃圾链接黑名单请求]]已有回应,请前往查看。', hant: '您的[[MediaWiki talk:Spam-blacklist|垃圾連結黑名單請求]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[MediaWiki talk:Spam-blacklist]]的通知', hant: '有關[[MediaWiki talk:Spam-blacklist]]的通知' })
},
shl: {
label: 'Spam-whitelist',
title: conv({ hans: '垃圾链接白名单请求有新回应', hant: '垃圾連結白名單請求有新回應' }),
content: conv({ hans: '您的[[MediaWiki talk:Spam-whitelist|垃圾链接白名单请求]]已有回应,请前往查看。', hant: '您的[[MediaWiki talk:Spam-whitelist|垃圾連結白名單請求]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[MediaWiki talk:Spam-whitelist]]的通知', hant: '有關[[MediaWiki talk:Spam-whitelist]]的通知' })
}
};
Twinkle.talkback.evaluate = function(e) {
var form = e.target;
var tbtarget = form.getChecked('tbtarget')[0];
var page, message;
var section = form.section.value;
var editSummary;
if (tbtarget === 'notice') {
page = form.noticeboard.value;
editSummary = Twinkle.talkback.noticeboards[page].editSummary;
} else {
// usertalk, other, see
page = form.page ? form.page.value : mw.config.get('wgUserName');
if (form.message) {
message = form.message.value.trim();
}
if (tbtarget === 'mail') {
editSummary = conv({ hans: '通知:有新邮件', hant: '通知:有新郵件' });
} else if (tbtarget === 'see') {
editSummary = conv({ hans: '请看看', hant: '請看看' }) + '[[:' + page + (section ? '#' + section : '') + ']]' + conv({ hans: '上的讨论', hant: '上的討論' });
} else { // tbtarget one of mytalk, usertalk, other
editSummary = conv({ hans: '回复通告', hant: '回覆通告' }) + '([[:';
if (tbtarget !== 'other' && !new RegExp('^\\s*' + Morebits.namespaceRegex(3) + ':', 'i').test(page)) {
editSummary += 'User talk:';
}
editSummary += page + (section ? '#' + section : '') + ']])';
}
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var fullUserTalkPageName = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user_talk] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = fullUserTalkPageName;
Morebits.wiki.actionCompleted.notice = conv({ hans: '回复通告完成,将在几秒内刷新页面', hant: '回覆通告完成,將在幾秒內重新整理頁面' });
Morebits.wiki.flow.check(fullUserTalkPageName, function () {
var data = Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message);
var title = data[1], content = data[2];
var flowpage = new Morebits.wiki.flow(fullUserTalkPageName, conv({ hans: '加入回复通告', hant: '加入回覆通告' }));
flowpage.setTopic(title);
flowpage.setContent(content);
flowpage.newTopic();
}, function () {
var text = '\n\n' + Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message)[0];
var talkpage = new Morebits.wiki.page(fullUserTalkPageName, conv({ hans: '加入回复通告', hant: '加入回覆通告' }));
talkpage.setEditSummary(editSummary);
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setAppendText(text);
talkpage.setCreateOption('recreate');
talkpage.setMinorEdit(Twinkle.getPref('markTalkbackAsMinor'));
talkpage.setFollowRedirect(true);
talkpage.append();
});
};
Twinkle.talkback.preview = function(form) {
var tbtarget = form.getChecked('tbtarget')[0];
var section = form.section.value;
var page, message;
if (tbtarget === 'notice') {
page = form.noticeboard.value;
} else {
// usertalk, other, see
page = form.page ? form.page.value : mw.config.get('wgUserName');
if (form.message) {
message = form.message.value.trim();
}
}
var noticetext = Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message)[0];
form.previewer.beginRender(noticetext, 'User_talk:' + Morebits.wiki.flow.relevantUserName()); // Force wikitext/correct username
};
Twinkle.talkback.getNoticeWikitext = function(tbtarget, page, section, message) {
var text;
var title, content;
if (tbtarget === 'notice') {
title = Twinkle.talkback.noticeboards[page].title;
content = Morebits.string.safeReplace(Twinkle.talkback.noticeboards[page].content, '$SECTION', section);
text = '== ' + title + ' ==\n' + content;
} else if (tbtarget === 'see') {
title = page + conv({ hans: '的相关讨论', hant: '的相關討論' });
content = '{{subst:Please see|location=' + page + (section ? '#' + section : '') + '|more=' + message.trim() + '}}';
text = '{{subst:Please see|location=' + page + (section ? '#' + section : '') + '|more=' + message.trim() + '}}';
} else {
text = '==';
if (tbtarget === 'mail') {
title = Twinkle.getPref('mailHeading');
content = "{{You've got mail|subject=" + section + '|ts=~~~~~}}';
text += Twinkle.getPref('mailHeading') + '==\n' + "{{You've got mail|subject=" + section;
} else { // tbtarget one of mytalk, usertalk, other
// clean talkback heading: strip section header markers that were erroneously suggested in the documentation
title = Twinkle.getPref('talkbackHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, '$1');
content = '{{talkback|' + page + (section ? '|' + section : '');
text += Twinkle.getPref('talkbackHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, '$1') +
'==\n' + '{{talkback|' + page + (section ? '|' + section : '');
}
content += '|ts=~~~~~}}';
text += '|ts=~~~~~}}';
if (message) {
content += '\n' + message;
text += '\n' + message + ' ~~~~';
} else if (Twinkle.getPref('insertTalkbackSignature')) {
text += '\n~~~~';
}
}
return [text, title, content];
};
Twinkle.addInitCallback(Twinkle.talkback, 'talkback');
})(jQuery);
// </nowiki>
a2c30de6997bec15342227ae0ad6c382578c139e
MediaWiki:Gadget-friendlywelcome.js
8
154
310
2023-11-06T13:17:52Z
zhwp>Xiplus
0
Repo at 5ca4449: Replace wgULS with HanAssist (#301)
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlywelcome.js: Welcome module
****************************************
* Mode of invocation: Tab ("Wel"), or from links on diff pages
* Active on: Any page with relevant user name (userspace,
* contribs, etc.) and diff pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.welcome = function friendlywelcome() {
if (mw.util.getParamValue('friendlywelcome')) {
if (mw.util.getParamValue('friendlywelcome') === 'auto') {
Twinkle.welcome.auto();
} else {
Twinkle.welcome.semiauto();
}
} else {
Twinkle.welcome.normal();
}
};
Twinkle.welcome.auto = function() {
if (mw.util.getParamValue('action') !== 'edit') {
// userpage not empty, aborting auto-welcome
return;
}
Twinkle.welcome.welcomeUser();
};
Twinkle.welcome.semiauto = function() {
Twinkle.welcome.callback(Morebits.wiki.flow.relevantUserName());
};
Twinkle.welcome.normal = function() {
if (mw.util.getParamValue('diff')) {
// check whether the contributors' talk pages exist yet
var $oList = $('#mw-diff-otitle2').find('span.mw-usertoollinks a.new.mw-usertoollinks-talk').first();
var $nList = $('#mw-diff-ntitle2').find('span.mw-usertoollinks a.new.mw-usertoollinks-talk').first();
if ($oList.length > 0 || $nList.length > 0) {
var spanTag = function(color, content) {
var span = document.createElement('span');
span.style.color = color;
span.appendChild(document.createTextNode(content));
return span;
};
var welcomeNode = document.createElement('strong');
var welcomeLink = document.createElement('a');
welcomeLink.appendChild(spanTag('Black', '['));
welcomeLink.appendChild(spanTag('Goldenrod', conv({ hans: '欢迎', hant: '歡迎' })));
welcomeLink.appendChild(spanTag('Black', ']'));
welcomeNode.appendChild(welcomeLink);
if ($oList.length > 0) {
var oHref = $oList.attr('href');
var oWelcomeNode = welcomeNode.cloneNode(true);
oWelcomeNode.firstChild.setAttribute('href', oHref + '&' + $.param({
friendlywelcome: Twinkle.getPref('quickWelcomeMode') === 'auto' ? 'auto' : 'norm',
vanarticle: Morebits.pageNameNorm
}));
$oList[0].parentNode.parentNode.appendChild(document.createTextNode(' '));
$oList[0].parentNode.parentNode.appendChild(oWelcomeNode);
}
if ($nList.length > 0) {
var nHref = $nList.attr('href');
var nWelcomeNode = welcomeNode.cloneNode(true);
nWelcomeNode.firstChild.setAttribute('href', nHref + '&' + $.param({
friendlywelcome: Twinkle.getPref('quickWelcomeMode') === 'auto' ? 'auto' : 'norm',
vanarticle: Morebits.pageNameNorm
}));
$nList[0].parentNode.parentNode.appendChild(document.createTextNode(' '));
$nList[0].parentNode.parentNode.appendChild(nWelcomeNode);
}
}
}
if (Morebits.wiki.flow.relevantUserName()) {
Twinkle.addPortletLink(function() {
Twinkle.welcome.callback(Morebits.wiki.flow.relevantUserName());
}, conv({ hans: '欢迎', hant: '歡迎' }), 'friendly-welcome', conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
}
};
Twinkle.welcome.welcomeUser = function welcomeUser() {
Morebits.status.init(document.getElementById('mw-content-text'));
$('#catlinks').remove();
var params = {
template: Twinkle.getPref('quickWelcomeTemplate'),
article: mw.util.getParamValue('vanarticle') || '',
mode: 'auto'
};
var userTalkPage = mw.config.get('wgFormattedNamespaces')[3] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '欢迎完成,将在几秒内刷新页面', hant: '歡迎完成,將在幾秒內重新整理頁面' });
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '编辑用户讨论页', hant: '編輯使用者討論頁' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.welcome.callbacks.main);
};
Twinkle.welcome.callback = function friendlywelcomeCallback(uid) {
if (uid === mw.config.get('wgUserName') && !confirm(conv({ hans: '您真的要欢迎您自己吗?', hant: '您真的要歡迎您自己嗎?' }))) {
return;
}
var Window = new Morebits.simpleWindow(600, 420);
Window.setTitle(conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '欢迎设置', hant: '歡迎設定' }), 'WP:TW/PREF#welcome');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'H:TW#欢迎');
var form = new Morebits.quickForm(Twinkle.welcome.callback.evaluate);
form.append({
type: 'select',
name: 'type',
label: conv({ hans: '欢迎类型:', hant: '歡迎類別:' }),
event: Twinkle.welcome.populateWelcomeList,
list: [
{ type: 'option', value: 'standard', label: conv({ hans: '标准欢迎', hant: '標準歡迎' }), selected: !mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName()) },
{ type: 'option', value: 'anonymous', label: conv({ hans: '欢迎IP用户', hant: '歡迎IP使用者' }), selected: mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName()) },
{ type: 'option', value: 'nonChinese', label: conv({ hans: '非中文欢迎', hant: '非中文歡迎' }) }
]
});
form.append({
type: 'div',
id: 'welcomeWorkArea',
className: 'morebits-scrollbox'
});
form.append({
type: 'input',
name: 'article',
label: conv({ hans: '* 条目链接(如果模板支持):', hant: '* 條目連結(如果模板支援):' }),
value: mw.util.getParamValue('vanarticle') || '',
tooltip: conv({ hans: '如果模板支持则可以链接到条目,留空则不链接。支持链接的模板以星号标注。', hant: '如果模板支援則可以連結到條目,留空則不連結。支援連結的模板以星號標註。' })
});
// Only displayed when the user viewing the user talk page
if (mw.config.get('wgNamespaceNumber') === 3 && mw.config.get('wgTitle') === Morebits.wiki.flow.relevantUserName()) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '欢迎前清空用户讨论页', hant: '歡迎前清空使用者討論頁' }),
value: 'blank',
name: 'blank',
tooltip: conv({ hans: '适用于用户讨论页面上仅有胡言乱语或编辑测试时。', hant: '適用於使用者討論頁面上僅有胡言亂語或編輯測試時。' })
}
]
});
}
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.welcome.callbacks.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
form.append({ type: 'div', name: 'welcomepreview', label: [ previewlink ] });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// initialize the welcome list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.type.dispatchEvent(evt);
};
Twinkle.welcome.populateWelcomeList = function(e) {
var type = e.target.value;
var container = new Morebits.quickForm.element({ type: 'fragment' });
if ((type === 'standard' || type === 'anonymous') && Twinkle.getPref('customWelcomeList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义欢迎模板', hant: '自訂歡迎模板' }) });
container.append({
type: 'radio',
name: 'template',
list: Twinkle.getPref('customWelcomeList'),
event: function() {
e.target.form.article.disabled = false;
}
});
}
var sets = Twinkle.welcome.templates[type];
$.each(sets, function(label, templates) {
container.append({ type: 'header', label: label });
container.append({
type: 'radio',
name: 'template',
list: $.map(templates, function(properties, template) {
return {
value: template,
label: '{{' + template + '}}:' + properties.description + (properties.linkedArticle ? '\u00A0*' : ''), // U+00A0 NO-BREAK SPACE
tooltip: properties.tooltip // may be undefined
};
}),
event: function(ev) {
ev.target.form.article.disabled = !templates[ev.target.value].linkedArticle;
}
});
});
var rendered = container.render();
$(e.target.form).find('div#welcomeWorkArea').empty().append(rendered);
var firstRadio = e.target.form.template[0] || e.target.form.template;
firstRadio.checked = true;
var vals = sets[Object.keys(sets)[0]];
e.target.form.article.disabled = vals[firstRadio.value] ? !vals[firstRadio.value].linkedArticle : true;
};
// A list of welcome templates and their properties and syntax
// The four fields that are available are "description", "linkedArticle", "syntax", and "tooltip".
// The three magic words that can be used in the "syntax" field are:
// - $USERNAME$ - replaced by the welcomer's username, depending on user's preferences
// - $ARTICLE$ - replaced by an article name, if "linkedArticle" is true
// - $HEADER$ - adds a level 2 header (most templates already include this)
Twinkle.welcome.templates = {
standard: {
[conv({ hans: '一般欢迎模板', hant: '一般歡迎模板' })]: {
Welcome: {
description: conv({ hans: '标准欢迎', hant: '標準歡迎' }),
syntax: '{{subst:Welcome}}'
}
},
[conv({ hans: '问题用户欢迎模板', hant: '問題使用者歡迎模板' })]: {
Firstarticle: {
description: conv({ hans: '给第一篇条目不符条目创建指引的用户', hant: '給第一篇條目不符條目建立指引的使用者' }),
linkedArticle: true,
syntax: '{{subst:Firstarticle|1=$ARTICLE$}}'
}
}
},
anonymous: {
[conv({ hans: '匿名用户欢迎模板', hant: '匿名使用者歡迎模板' })]: {
Welcomeip: {
description: conv({ hans: '供匿名用户,鼓励其创建账户', hant: '供匿名使用者,鼓勵其建立帳戶' }),
syntax: '{{subst:Welcomeip}}'
}
}
},
nonChinese: {
[conv({ hans: '非中文欢迎模板', hant: '非中文歡迎模板' })]: {
Welcomeen: {
description: conv({ hans: '欢迎非中文用户', hant: '歡迎非中文使用者' }),
linkedArticle: true,
syntax: '{{subst:Welcomeen|art=$ARTICLE$}}'
}
}
}
};
/* eslint-enable quote-props */
Twinkle.welcome.getTemplateWikitext = function(type, template, article) {
// the iteration is required as the type=standard has two groups
var properties;
$.each(Twinkle.welcome.templates[type], function(label, templates) {
properties = templates[template];
if (properties) {
return false; // break
}
});
if (properties) {
return properties.syntax.
replace('$USERNAME$', Twinkle.getPref('insertUsername') ? mw.config.get('wgUserName') : '').
replace('$ARTICLE$', article ? article : '').
replace(/\$HEADER\$\s*/, '== ' + conv({ hans: '欢迎', hant: '歡迎' }) + ' ==\n\n').
replace('$EXTRA$', ''); // EXTRA is not implemented yet
}
return '{{subst:' + template + (article ? '|art=' + article : '') + '}}' +
(Twinkle.getPref('customWelcomeSignature') ? ' ~~~~' : '');
};
Twinkle.welcome.callbacks = {
preview: function(form) {
var previewDialog = new Morebits.simpleWindow(750, 400);
previewDialog.setTitle(conv({ hans: '预览欢迎模板', hant: '預覽歡迎模板' }));
previewDialog.setScriptName(conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
previewDialog.setModality(true);
var previewdiv = document.createElement('div');
previewdiv.style.marginLeft = previewdiv.style.marginRight = '0.5em';
previewdiv.style.fontSize = 'small';
previewDialog.setContent(previewdiv);
var previewer = new Morebits.wiki.preview(previewdiv);
var input = Morebits.quickForm.getInputData(form);
previewer.beginRender(Twinkle.welcome.getTemplateWikitext(input.type, input.template, input.article), 'User talk:' + Morebits.wiki.flow.relevantUserName()); // Force wikitext/correct username
var submit = document.createElement('input');
submit.setAttribute('type', 'submit');
submit.setAttribute('value', conv({ hans: '关闭', hant: '關閉' }));
previewDialog.addContent(submit);
previewDialog.display();
$(submit).click(function() {
previewDialog.close();
});
},
main: function(pageobj) {
var params = pageobj.getCallbackParameters();
var text = pageobj.getPageText();
// abort if mode is auto and form is not empty
if (pageobj.exists() && params.mode === 'auto') {
Morebits.status.info('警告', conv({ hans: '用户讨论页不是空的,略过自动欢迎', hant: '使用者討論頁不是空的,略過自動歡迎' }));
Morebits.wiki.actionCompleted.event();
return;
}
var welcomeText = Twinkle.welcome.getTemplateWikitext(params.type, params.template, params.article);
if (params.blank) {
text = '';
}
if (Twinkle.getPref('topWelcomes')) {
text = welcomeText + '\n\n' + text;
} else {
text += '\n' + welcomeText;
}
var summaryText = conv({ hans: '欢迎来到维基百科!', hant: '歡迎來到維基百科!' });
pageobj.setPageText(text);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchWelcomes'));
pageobj.setCreateOption('recreate');
pageobj.save();
}
};
Twinkle.welcome.callback.evaluate = function friendlywelcomeCallbackEvaluate(e) {
var form = e.target;
var params = Morebits.quickForm.getInputData(form); // : type, template, article
params.mode = 'manual';
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var userTalkPage = mw.config.get('wgFormattedNamespaces')[3] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '欢迎完成,将在几秒内刷新讨论页面', hant: '歡迎完成,將在幾秒內重新整理討論頁面' });
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '修改用户讨论页', hant: '修改使用者討論頁' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.welcome.callbacks.main);
};
Twinkle.addInitCallback(Twinkle.welcome, 'welcome');
})(jQuery);
// </nowiki>
61091408bf8564378e22a5a932ca0c8850316f3f
Template:Script
10
326
677
2023-11-07T16:16:04Z
zhwp>白布飘扬
0
wikitext
text/x-wiki
{{#switch: {{{1|}}}
<!--scripts with dedicated templates-->
|Arab = {{script/Arabic|1={{{2}}}}}
|fa-Arab = {{script/Nastaliq|1={{{2}}}|2=fa}}
|ps-Arab = {{script/Nastaliq|1={{{2}}}|2=ps}}
|ur-Arab = {{script/Nastaliq|1={{{2}}}}}
|Aran = {{script/Nastaliq|1={{{2}}}}}
|Armi = {{script/Aramaic|1={{{2}}}}}
|Avst = {{script/Avestan|1={{{2}}}}}
|Bali = {{script/Bali|1={{{2}}}}}
|Bamu = {{script/Bamum|1={{{2}}}}}
|Bhks = {{Script/Bhaiksuki|1={{{2}}}}}
|Brah = {{script/Brahmi|1={{{2}}}}}
|Bugi = {{script/Lontara|2={{{2}}}}}
|Buhd = {{script/Buhid|1={{{2}}}}}
|Copt = {{script/Coptic|1={{{2}}}}}
|Chak = {{script/Chakma|1={{{2}}}}}
|Cham = {{script/Cham|1={{{2}}}}}
|Cpmn = {{Script/Cypro-Minoan|1={{{2}}}}}
|Cyrs = {{script/Slavonic|1={{{2}}}}}
|Dupl = {{Script/Duployan|1={{{2}}}}}
|Ethi = {{script/Ethiopic|1={{{2}}}}}
|Geok = {{script/Khutsuri|1={{{2}}}}}
|Glag = {{script/Glagolitic|1={{{2}}}}}
|Goth = {{script/Gothic|1={{{2}}}}}
|Grek = {{script/Greek|1={{{2}}}}}
|Hebr = {{script/Hebrew|1={{{2}}}}}
|Ital = {{script/Old Italic|1={{{2}}}}}
|Java = {{script/Java|1={{{2}}}}}
|Kali = {{script/Kayah Li|1={{{2}}}}}
|Khmr = {{script/Khmer|1={{{2}}}}}
|Kits = {{Script/Khitan Small Script|1={{{2}}}}}<!-- 契丹小字 -->
|Latg = {{script/Gaelic|1={{{2}}}}}
|Lana = {{script/Tai Tham|1={{{2}}}}}
|Limbu = {{script/Limbu|1={{{2}}}}}
|Lisu|Fraser = {{script/Lisu|1={{{2}}}}}
|Marc = {{Script/Marchen|1={{{2}}}}}
|Meithei = {{script/Meithei|1={{{2}}}}}
|Mymr = {{script/Mymr|1={{{2}}}}}
|Newa = {{Script/Newa|1={{{2}}}}}
|Nkoo|Nko = {{script/Nko|1={{{2}}}}}
|Nshu = {{Script/Nushu|1={{{2}}}}}<!-- 女書 -->
|Perm = {{Script/Old Permic|1={{{2}}}}}
|Ogam = {{script/Ogam|1={{{2}}}}}
|Orkh = {{script/Orkhon|1={{{2}}}}}
|Osma = {{script/Osmanya|1={{{2}}}}}
|Phnx = {{script/Phoenician|1={{{2}}}}}
|Piqd = {{script/Klingon|1={{{2}}}}}
|Pollard = {{script/Pollard|1={{{2}}}}}
|Rjng = {{script/Rejang|1={{{2}}}}}
|Runr = {{script/Runic|1={{{2}}}}}
|Samr|Smrt = {{script/Samaritan|1={{{2}}}}}
|Sidd = {{script/Siddham|1={{{2}}}}}
|Sylo = {{script/Syloti|1={{{2}}}}}
|Syre = {{script/Strng|1={{{2}}}}}
|Syrj = {{script/Serto|1={{{2}}}}}
|Syrn = {{script/Mdnh|1={{{2}}}}}
|Tagb = {{script/Tagbanwa|1={{{2}}}}}
|Talu = {{script/New Tai Lue|1={{{2}}}}}
|Tavt = {{script/Tai Viet|1={{{2}}}}}
|Tglg = {{script/Baybayin|1={{{2}}}}}
|Tfng = {{script/Tifinagh|1={{{2}}}}}
|Vaii|Vai = {{script/Vai|1={{{2}}}}}
|Xsux = {{script/Cuneiform|1={{{2}}}}}
|Yiii|Yi = {{script/Yi|1={{{2}}}}}
<!--other scripts use standard language spans-->
|#default = <span {{#switch: {{{1}}}
<!--tweaks which should be moved to global CSS classes, with fonts supported in the Universal Language Selector-->
|Cprt = style="font-size:125%;font-family:'Segoe UI Historic','Noto Sans Cypriot', Code2001;"<!--SMP, rarely supported, state font explicitly-->
|Hano = style="font-size:125%;font-family:'Noto Sans Hanunoo', 'FreeSerif', Quivira;"
|Latf|de-Latf = style="font-size:125%;font-family:'Breitkopf Fraktur',UnifrakturCook,UniFrakturMaguntia,'MarsFraktur','MarsFraktur OT','KochFraktur','KochFraktur OT','OffenbacherSchwabOT';"
|en-Latf = style="font-size:125%;font-family:Cankama,'Old English Text MT','Textura Libera','Textura Libera Tenuis',London;"
|it-Latf = style="font-size:125%;font-family:'Rotunda Pommerania',Rotunda,'Typographer Rotunda';"
|th-Khom = style="font-size:200%;font-family:'SOV_jarukbali', 'Patimokka', 'KhomPaliForXP';"
|Linb = style="font-size:125%;font-family:'Noto Sans Linear B'"
<!-- |Smrt = style="font-size:125%;font-family:'Noto Sans Samaritan'" added above as Samr -->
|Ugar = style="font-size:125%;font-family:'Segoe UI Historic', 'Noto Sans Ugaritic', Aegean"
|Xpeo = style="font-size:125%;font-family:'Segoe UI Historic',Artaxerxes,Xerxes,Aegean;"<!--Use Xerxes for Old Persian-->
|#default = class="Unicode"<!--BMP, use generic "unicode" CSS class for all other scripts, including "Latn" for IPA-->
}}>{{{2}}}</span>
}}<noinclude>
{{template doc}}<!-- Add categories, documentation, and interwiki links to the /doc subpage, not here! -->
</noinclude>
ce29154979e43ecd528fb7c88fbdb574b0e3c91f
Module:Parameter names example
828
222
462
2023-11-21T16:05:49Z
zhwp>Taeas
0
Scribunto
text/plain
-- This module implements {{parameter names example}}.
local p = {}
local function makeParam(s)
local lb = '{'
local rb = '}'
return lb:rep(3) .. s .. rb:rep(3)
end
local function italicize(s)
return "''" .. s .. "''"
end
local function plain(s)
return s
end
function p._main(args, frame)
-- Find how we want to format the arguments to the template.
local formatFunc
if args._display == 'italics' or args._display == 'italic' then
formatFunc = italicize
elseif args._display == 'plain' then
formatFunc = plain
else
formatFunc = makeParam
end
-- Build the table of template arguments.
local targs = {}
for k, v in pairs(args) do
if type(k) == 'number' then
targs[v] = formatFunc(v)
elseif not k:find('^_') then
targs[k] = v
end
end
--targs['nocat'] = 'yes';
--targs['categories'] = 'no';
--targs['demo'] = 'yes';
-- Find the template name.
local template
if args._template then
template = args._template
else
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.prefixedText:find('/sandbox$') then
template = currentTitle.prefixedText
else
template = currentTitle.basePageTitle.prefixedText
end
end
-- Call the template with the arguments.
frame = frame or mw.getCurrentFrame()
local success, result = pcall(
frame.expandTemplate,
frame,
{title = template, args = targs}
)
if success then
return result
else
return ''
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Parameter names example'
})
return p._main(args, frame)
end
return p
fdf94fb7a5dc1fabf118d60488a02f1e65b0df24
Module:Icon/data
828
89
172
2023-12-10T10:35:12Z
zhwp>Peacearth
0
per [[Special:Diff/77883390/80058153|request]]
Scribunto
text/plain
-- This module stores icon data for [[Module:Icon]].
--------------------------------------------------------------------------------
-- Icon data
--------------------------------------------------------------------------------
local data = {
fa = {
image = "Featured article star.svg",
tooltip = "典范条目",
},
far = {
image = "Cscr-star piece.png",
tooltip = "典范条目候选",
},
farc = {
image = "Cscr-star piece.png",
tooltip = "典范条目重审",
},
ffa = {
aliases = {"dfa"},
image = "Featured article star - cross.svg",
tooltip = "已被撤销的典范条目",
},
fac = {
aliases = {"fan"},
image = "Cscr-candidate.svg",
tooltip = "典范条目评选",
},
ffac = {
aliases = {"nofa"},
image = "Featured article star - cross.svg",
tooltip = "落选典范条目",
},
fl = {
image = "Featured article star.svg",
tooltip = "特色列表",
},
flrc = {
aliases = {"flr"},
image = "Cscr-star piece.png",
tooltip = "特色列表重审",
},
ffl = {
aliases = {"dfl"},
image = "Cscr-featured-strike.svg",
tooltip = "已被撤销的特色列表",
},
flc = {
aliases = {"fln"},
image = "Cscr-candidate.svg",
tooltip = "特色列表候选",
},
fflc = {
aliases = {"nofl"},
image = "Featured article star - cross.svg",
tooltip = "落选特色列表",
},
a = {
image = "Symbol a class.svg",
tooltip = "甲级条目",
},
dac = {
aliases = {"daa"},
image = "Symbol unsupport A vote.svg",
tooltip = "已降级甲级条目",
},
acc = {
aliases = {"acn", "aac"},
image = "A candidate.svg",
tooltip = "甲级条目候选",
},
noac = {
aliases = {"faac"},
image = "Symbol unsupport A vote.svg",
tooltip = "落选甲级条目",
},
ga = {
image = "Symbol support vote.svg",
tooltip = "优良条目",
},
gar = {
image = "GA Candidate Neutral vote(ChaosNil).svg",
tooltip = "优良条目重审",
},
dga = {
image = "Symbol unsupport vote.svg",
tooltip = "已被撤销的优良条目",
},
gan = {
aliases = {"gac"},
image = "GA candidate.svg",
tooltip = "优良条目候选",
},
ga2 = {
image = "Symbol neutral vote.svg",
tooltip = "寻求意见的优良条目",
},
gah = {
image = "Symbol wait.svg",
tooltip = "搁置的优良条目",
},
fgan = {
aliases = {"noga", "gaf", "gf"},
image = "Symbol oppose vote.svg",
tooltip = "落选优良条目",
},
fp = {
image = "Cscr-featured.svg",
tooltip = "特色图片",
},
fpc = {
aliases = {"fpn"},
image = "Cscr-candidate.svg",
tooltip = "特色图片候选",
},
ffpc = {
aliases = {"nofp"},
image = "Featured article star - cross.svg",
tooltip = "落选特色图片",
},
ffp = {
image = "Featured article star - cross.svg",
tooltip = "已被撤销的特色图片",
},
vp = {
image = "ENWP VP Logo.svg",
tooltip = "珍贵图片",
},
vpc = {
image = "Valued pics 1.svg",
tooltip = "珍贵图片候选",
},
fs = {
image = "Cscr-featured.svg",
tooltip = "特色声音",
},
ffs = {
image = "Cscr-former.svg",
tooltip = "已被撤销的特色声音",
},
fsc = {
image = "Cscr-candidate.svg",
tooltip = "特色声音候选",
},
fpo = {
image = "Cscr-featured.svg",
tooltip = "特色主题",
},
fpor = {
image = "Cscr-star piece.png",
tooltip = "特色主题评选",
},
ffpo = {
image = "Featured article star - cross.svg",
tooltip = "已被撤销的特色主题",
},
fpoc = {
image = "Cscr-candidate.svg",
tooltip = "特色主题候选",
},
ft = {
image = "Cscr-featuredtopic.svg",
tooltip = "特色话题",
},
ftrc = {
image = "Cscr-star piece.png",
tooltip = "特色话题重审",
},
fft = {
aliases = {"dft"},
image = "DFT candidate_cluster.svg",
tooltip = "已被撤销的特色话题",
},
ftc = {
aliases = {"ftn"},
image = "FT candidate cluster.svg",
tooltip = "特色话题候选",
},
gt = {
image = "Support cluster.svg",
tooltip = "优良话题",
},
gtrc = {
image = "Symbol unsupport vote.svg",
tooltip = "优良话题重审",
},
gtc = {
aliases = {"gtn"},
image = "GA candidate cluster.svg",
tooltip = "优良话题候选",
},
bplus = {
aliases = {"b+"},
image = "Symbol bplus class.svg",
tooltip = "乙+级条目",
},
b = {
image = "Symbol b class.svg",
tooltip = "乙级条目",
},
br = {
aliases = {"bcr"},
image = "Bclass-checklist.svg",
tooltip = "乙级条目评选",
},
c = {
image = "Symbol c class.svg",
tooltip = "丙级条目",
},
start = {
image = "Symbol start class.svg",
tooltip = "初级条目",
},
stub = {
image = "Symbol stub class.svg",
tooltip = "小作品级条目",
},
list = {
aliases = {"comparison"},
image = "Symbol list class.svg",
tooltip = "列表级条目",
},
no = {
image = "Crystal button cancel.svg",
tooltip = "未知分级条目",
},
book = {
image = "Symbol book class2.svg",
tooltip = "维基百科图书",
},
category = {
aliases = {"cat", "categ"},
image = "Symbol category class.svg",
tooltip = "分类",
},
disambiguation = {
aliases = {"dab", "disamb", "disambig"},
image = "Symbol dab class.svg",
tooltip = "消歧义页",
},
image = {
aliases = {"file"},
image = "Video-x-generic.svg",
tooltip = "文件",
},
portal = {
image = "Symbol portal class.svg",
tooltip = "主题",
},
project = {
image = "Symbol information vote.svg",
tooltip = "项目页面",
},
redirect = {
aliases = {"red", "redir"},
image = "Symbol redirect vote2.svg",
tooltip = "重定向页",
},
template = {
aliases = {"temp", "templ"},
image = "Symbol template class.svg",
tooltip = "模板",
},
essay = {
image = "Essay.svg",
tooltip = "论述",
},
na = {
image = "Symbol neutral vote.svg",
tooltip = "非条目页面",
},
aa = {
image = "Yes check.svg",
tooltip = "限定主题的已审条目",
},
da = {
image = "Symbol oppose vote.svg",
tooltip = "降级条目",
},
dyk = {
image = "Symbol question.svg",
tooltip = "你知道吗?",
},
dyk2 = {
image = "DYK questionmark icon.svg",
tooltip = "你知道吗?",
},
dykc = {
aliases = {"dykn"},
image = "DYK candidate.svg",
tooltip = "你知道吗?候选",
},
pr = {
image = "Nuvola apps kedit.png",
tooltip = "同行评审",
},
ppr = {
image = "Nuvola apps kedit.png",
tooltip = "主题同行评审",
},
q = {
aliases = {"question"},
image = "Symbol question.svg",
tooltip = "问题",
},
qi = {
image = "Quality images logo.svg",
tooltip = "维基共享资源优质图像",
},
vi = {
image = "Valued image seal.svg",
tooltip = "维基共享资源珍贵图像",
},
tfa = {
image = "Wikipedia-logo.svg",
tooltip = "今日典范条目",
},
itn = {
image = "Globe current.svg",
tooltip = "新闻动态",
},
otd = {
image = "Nuvola apps date.svg",
tooltip = "历史上的今天",
},
wikiproject = {
image = "People icon.svg",
tooltip = "专题",
},
wikipedia = {
image = "Wikipedia-logo.svg",
tooltip = "维基百科页面",
},
commons = {
image = "Commons-logo.svg",
tooltip = "共享资源页面",
},
wikiquote = {
image = "Wikiquote-logo.svg",
tooltip = "维基语录页面",
},
wikiversity = {
image = "Wikiversity-logo.svg",
tooltip = "维基学院页面",
},
wikibooks = {
image = "Wikibooks-logo.svg",
tooltip = "维基教科书页面",
},
wikisource = {
image = "Wikisource-logo.svg",
tooltip = "维基文库页面",
},
wiktionary = {
image = "Wiktionary-logo.svg",
tooltip = "维基词典页面",
},
wikinews = {
image = "Wikinews-logo.svg",
tooltip = "维基新闻页面",
},
wikispecies = {
image = "Wikispecies-logo.svg",
tooltip = "维基物种页面",
},
wikidata = {
image = "Wikidata-logo.svg",
tooltip = "维基数据页面",
},
wikivoyage = {
image = "Wikivoyage-logo.svg",
tooltip = "维基导游页面",
},
meta = {
image = "Wikimedia Community Logo.svg",
tooltip = "元维基页面",
},
four = {
image = "Four Award.svg",
tooltip = "Four Award",
},
million = {
image = "Million award logo.svg",
tooltip = "Million Award",
},
dc = {
aliases = {"DC"},
image = "Wikipedia_zh_dc_logo.svg",
tooltip = "维基百科动员令",
},
wam = {
aliases = {"WAM"},
image = "WAM_logo_without_text.svg",
tooltip = "维基百科亚洲月",
},
wafm = {
aliases = {"WAFM"},
image = "African_Month_Medal.svg",
tooltip = "维基百科非洲月",
},
-- WP:VA usage
vaa = {
image = "Yes check.svg",
tooltip = "> 30 KB",
},
vab = {
image = "Yes check lines.svg",
tooltip = "10 - 30 KB",
},
vac = {
image = "QSicon in Arbeit.svg",
tooltip = "3 - 10 KB",
},
_DEFAULT = {
image = "Symbol question.svg",
}
}
--------------------------------------------------------------------------------
-- End icon data
--------------------------------------------------------------------------------
-- Make aliases work the same as normal keys, and remove the "aliases" subtables.
for k, t in pairs(data) do
if t.aliases then
for i, alias in ipairs(t.aliases) do
data[alias] = t
end
t.aliases = nil
end
data[k] = t
end
return data
b388921315ecd10da77ae36a0172274d23560d2c
Module:Redirect
828
35
65
2023-12-21T14:54:41Z
zhwp>Shizhao
0
自[[Module:Redirect/sandbox]]合并[[Special:Contributions/A2569875|A2569875]]的[[Special:PermaLink/80196666|版本80196666]]
Scribunto
text/plain
-- This module provides functions for getting the target of a redirect page.
local p = {}
-- Gets a mw.title object, using pcall to avoid generating script errors if we
-- are over the expensive function count limit (among other possible causes).
local function getTitle(...)
local success, titleObj = pcall(mw.title.new, ...)
if success then
return titleObj
else
return nil
end
end
-- Gets the name of a page that a redirect leads to, or nil if it isn't a
-- redirect.
function p.getTargetFromText(text, contentModel)
contentModel = contentModel or 'wikitext'
if contentModel == 'wikitext' then
return string.match(
text,
"^%s*#重定向%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#重定向%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
)
elseif contentModel == 'Scribunto' then
return string.match(
text,
"^%s*return%s+require%s*%[%[([^%[%]|]-)%]%]" -- T120794
) or string.match(
text,
"^%s*return%s+require%s*%(%s*['\"]([^%[%]|]-)['\"]%s*%)"
)
end
return nil
end
-- Gets the target of a redirect. If the page specified is not a redirect,
-- returns nil.
function p.getTarget(page, fulltext)
-- Get the title object. Both page names and title objects are allowed
-- as input.
local titleObj
if type(page) == 'string' or type(page) == 'number' then
titleObj = getTitle(page)
elseif type(page) == 'table' and type(page.getContent) == 'function' then
titleObj = page
else
error(string.format(
"错误参数 #1,调用 'getTarget'"
.. " (需要字符串,数字,或标题对象;得到%s)",
type(page)
), 2)
end
if not titleObj or not titleObj.isRedirect then
return nil
end
-- Find the target by using string matching on the page content.
local target = p.getTargetFromText(titleObj:getContent() or "", titleObj.contentModel)
--優先使用原本的判斷方式,如果判斷不出來,再直接用redirectTarget
or titleObj.redirectTarget
if target then
local targetTitle = getTitle(target)
if targetTitle then
if fulltext then
return targetTitle.fullText
else
return targetTitle.prefixedText
end
else
return nil
end
else
-- The page is a redirect, but matching failed. This indicates a bug in
-- the redirect matching pattern, so throw an error.
error(string.format(
'无法处理页面"%s"上的重定向',
fulltext and titleObj.fullText or titleObj.prefixedText
))
end
end
--[[
-- Given a single page name determines what page it redirects to and returns the
-- target page name, or the passed page name when not a redirect. The passed
-- page name can be given as plain text or as a page link.
--
-- Returns page name as plain text, or when the bracket parameter is given, as a
-- page link. Returns an error message when page does not exist or the redirect
-- target cannot be determined for some reason.
--]]
function p.luaMain(rname, bracket, fulltext)
if type(rname) ~= "string" or not rname:find("%S") then
return nil
end
bracket = bracket and "[[%s]]" or "%s"
rname = rname:match("%[%[(.+)%]%]") or rname
local target = p.getTarget(rname, fulltext)
local ret = target or rname
ret = getTitle(ret)
if ret then
if fulltext then
ret = ret.fullText
else
ret = ret.prefixedText
end
return bracket:format(ret)
else
return nil
end
end
-- Provides access to the luaMain function from wikitext.
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
return p.luaMain(args[1], args.bracket, args.fulltext) or ''
end
-- Returns true if the specified page is a redirect, and false otherwise.
function p.luaIsRedirect(page)
local titleObj = getTitle(page)
if not titleObj then
return false
end
if titleObj.isRedirect then
return true
else
return false
end
end
-- Provides access to the luaIsRedirect function from wikitext, returning 'yes'
-- if the specified page is a redirect, and the blank string otherwise.
function p.isRedirect(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
if p.luaIsRedirect(args[1]) then
return 'yes'
else
return ''
end
end
return p
33015ebf3343aa4b100d4568e0d1fd69e0408235
Template:Tlp
10
254
525
2023-12-24T20:50:20Z
zhwp>Xiplus-abot
0
已保护“[[Template:Tlp]]”:高風險模板:507引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
<span style="white-space:nowrap;">{{{{#if:{{{1|}}}
| [[{{ns:Template}}:{{{1}}}|{{{1}}}]] | tlp|... }}<!--
-->{{#ifeq:{{{2|x}}}|{{{2|}}}| |{{{2}}} }}<!--
-->{{#ifeq:{{{3|x}}}|{{{3|}}}| |{{{3}}} }}<!--
-->{{#ifeq:{{{4|x}}}|{{{4|}}}| |{{{4}}} }}<!--
-->{{#ifeq:{{{5|x}}}|{{{5|}}}| |{{{5}}} }}<!--
-->{{#ifeq:{{{6|x}}}|{{{6|}}}| |{{{6}}} }}<!--
-->{{#ifeq:{{{7|x}}}|{{{7|}}}| |{{{7}}} }}<!--
-->{{#ifeq:{{{8|x}}}|{{{8|}}}| |{{{8}}} }}<!--
-->{{#ifeq:{{{9|x}}}|{{{9|}}}| |{{{9}}} }}<!--
-->}}</span><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
832a834204d293def8f65d96e27ed3f9464fc6d8
MediaWiki:Gadget-twinklespeedy.js
8
156
314
2023-12-29T14:01:26Z
zhwp>Xiplus
0
Repo at 98d0166: Add G18
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklespeedy.js: CSD module
****************************************
* Mode of invocation: Tab ("CSD")
* Active on: Non-special, existing pages
*
* NOTE FOR DEVELOPERS:
* If adding a new criterion, add it to the appropriate places at the top of
* twinkleconfig.js. Also check out the default values of the CSD preferences
* in twinkle.js, and add your new criterion to those if you think it would be
* good.
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.speedy = function twinklespeedy() {
// Disable on:
// * special pages
// * Flow pages
// * non-existent pages
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
return;
}
Twinkle.addPortletLink(Twinkle.speedy.callback, conv({ hans: '速删', hant: '速刪' }), 'tw-csd', Morebits.userIsSysop ? conv({ hans: '快速删除', hant: '快速刪除' }) : conv({ hans: '请求快速删除', hant: '請求快速刪除' }));
};
// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
Twinkle.speedy.initDialog(Morebits.userIsSysop ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};
// Used by unlink feature
Twinkle.speedy.dialog = null;
// Used throughout
Twinkle.speedy.hasCSD = !!$('#delete-reason').length;
// The speedy criteria list can be in one of several modes
Twinkle.speedy.mode = {
sysopSingleSubmit: 1, // radio buttons, no subgroups, submit when "Submit" button is clicked
sysopRadioClick: 2, // radio buttons, no subgroups, submit when a radio button is clicked
sysopMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already present
sysopMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
userMultipleSubmit: 5, // check boxes, subgroups, "Submit" button already pressent
userMultipleRadioClick: 6, // check boxes, subgroups, need to add a "Submit" button
userSingleSubmit: 7, // radio buttons, subgroups, submit when "Submit" button is clicked
userSingleRadioClick: 8, // radio buttons, subgroups, submit when a radio button is clicked
// are we in "delete page" mode?
// (sysops can access both "delete page" [sysop] and "tag page only" [user] modes)
isSysop: function twinklespeedyModeIsSysop(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
},
// do we have a "Submit" button once the form is created?
hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick ||
mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userSingleSubmit;
},
// is db-multiple the outcome here?
isMultiple: function twinklespeedyModeIsMultiple(mode) {
return mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
}
};
// Prepares the speedy deletion dialog and displays it
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
var dialog;
Twinkle.speedy.dialog = new Morebits.simpleWindow(Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight'));
dialog = Twinkle.speedy.dialog;
dialog.setTitle(conv({ hans: '选择快速删除理由', hant: '選擇快速刪除理由' }));
dialog.setScriptName('Twinkle');
dialog.addFooterLink(conv({ hans: '快速删除方针', hant: '快速刪除方針' }), 'WP:CSD');
dialog.addFooterLink(conv({ hans: '常见错误', hant: '常見錯誤' }), 'Wikipedia:管理员错误自查表/快速删除');
dialog.addFooterLink(conv({ hans: '速删设置', hant: '速刪設定' }), 'WP:TW/PREF#speedy');
dialog.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#speedy');
var form = new Morebits.quickForm(callbackfunc, Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null);
if (Morebits.userIsSysop) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '只标记,不删除', hant: '只標記,不刪除' }),
value: 'tag_only',
name: 'tag_only',
tooltip: conv({ hans: '如果您只想标记此页面而不是将其删除', hant: '如果您只想標記此頁面而不是將其刪除' }),
checked: !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToDelete')),
event: function(event) {
var cForm = event.target.form;
var cChecked = event.target.checked;
// enable/disable talk page checkbox
if (cForm.talkpage) {
cForm.talkpage.disabled = cChecked;
cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
}
// enable/disable redirects checkbox
cForm.redirects.disabled = cChecked;
cForm.redirects.checked = !cChecked;
// enable/disable delete multiple
cForm.delmultiple.disabled = cChecked;
cForm.delmultiple.checked = false;
// enable/disable open talk page checkbox
cForm.openusertalk.disabled = cChecked;
cForm.openusertalk.checked = false;
// enable/disable notify checkbox
cForm.notify.disabled = !cChecked;
cForm.notify.checked = cChecked;
// enable/disable multiple
cForm.multiple.disabled = !cChecked;
cForm.multiple.checked = false;
// enable requesting creation protection
cForm.salting.checked = false;
Twinkle.speedy.callback.modeChanged(cForm);
event.stopPropagation();
}
}
]
});
var deleteOptions = form.append({
type: 'div',
name: 'delete_options'
});
deleteOptions.append({
type: 'header',
label: conv({ hans: '删除相关选项', hant: '刪除相關選項' })
});
if (mw.config.get('wgNamespaceNumber') % 2 === 0 && mw.config.get('wgNamespaceNumber') !== 2) { // hide option for user pages, to avoid accidentally deleting user talk page
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除讨论页', hant: '刪除討論頁' }),
value: 'talkpage',
name: 'talkpage',
tooltip: conv({ hans: '删除时附带删除此页面的讨论页。', hant: '刪除時附帶刪除此頁面的討論頁。' }),
checked: Twinkle.getPref('deleteTalkPageOnDelete'),
event: function(event) {
event.stopPropagation();
}
}
]
});
}
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除重定向', hant: '刪除重新導向' }),
value: 'redirects',
name: 'redirects',
tooltip: conv({ hans: '删除到此页的重定向。', hant: '刪除到此頁的重新導向。' }),
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
event: function(event) {
event.stopPropagation();
}
}
]
});
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '应用多个理由删除', hant: '應用多個理由刪除' }),
value: 'delmultiple',
name: 'delmultiple',
tooltip: conv({ hans: '您可选择应用于该页的多个理由。', hant: '您可選擇應用於該頁的多個理由。' }),
event: function(event) {
Twinkle.speedy.callback.modeChanged(event.target.form);
event.stopPropagation();
}
}
]
});
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '开启用户讨论页', hant: '開啟使用者討論頁' }),
value: 'openusertalk',
name: 'openusertalk',
tooltip: conv({ hans: '此项的默认值为您的开启讨论页设置。在您选择应用多条理由删除时此项将保持不变。', hant: '此項的預設值為您的開啟討論頁設定。在您選擇應用多條理由刪除時此項將保持不變。' }),
checked: false
}
]
});
}
var tagOptions = form.append({
type: 'div',
name: 'tag_options'
});
if (Morebits.userIsSysop) {
tagOptions.append({
type: 'header',
label: conv({ hans: '标记相关选项', hant: '標記相關選項' })
});
}
tagOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,通知创建者', hant: '如可能,通知建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '一个通知模板将会被加入创建者的讨论页,如果您启用了该理据的通知。', hant: '一個通知模板將會被加入建立者的討論頁,如果您啟用了該理據的通知。' }),
checked: !Morebits.userIsSysop || !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToDelete')),
event: function(event) {
event.stopPropagation();
}
},
{
label: conv({ hans: '清空页面', hant: '清空頁面' }),
value: 'blank',
name: 'blank',
tooltip: conv({ hans: '在标记模板前,先清空页面,适用于严重破坏或负面生者传记等。', hant: '在標記模板前,先清空頁面,適用於嚴重破壞或負面生者傳記等。' })
},
{
label: conv({ hans: '同时标记以请求白纸保护', hant: '同時標記以請求白紙保護' }),
value: 'salting',
name: 'salting',
tooltip: conv({ hans: '选取后,快速删除模板后将附带 {{salt}} 标签,以请求执行删除的管理员进行白纸保护,仅在页面创建3次以上才选择此项。', hant: '選取後,快速刪除模板後將附帶 {{salt}} 標籤,以請求執行刪除的管理員進行白紙保護,僅在頁面建立3次以上才選擇此項。' })
},
{
label: conv({ hans: '应用多个理由', hant: '應用多個理由' }),
value: 'multiple',
name: 'multiple',
tooltip: conv({ hans: '您可选择应用于该页的多个理由。', hant: '您可選擇應用於該頁的多個理由。' }),
event: function(event) {
Twinkle.speedy.callback.modeChanged(event.target.form);
event.stopPropagation();
}
}
]
});
form.append({
type: 'div',
id: 'prior-deletion-count'
});
form.append({
type: 'div',
name: 'work_area',
label: conv({ hans: '初始化CSD模块失败,请重试,或将这报告给Twinkle开发者。', hant: '初始化CSD模組失敗,請重試,或將這報告給Twinkle開發者。' })
});
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
form.append({ type: 'submit', className: 'tw-speedy-submit' }); // Renamed in modeChanged
}
var result = form.render();
dialog.setContent(result);
dialog.display();
Twinkle.speedy.callback.modeChanged(result);
// Check for prior deletions. Just once, upon init
Twinkle.speedy.callback.priorDeletionCount();
};
Twinkle.speedy.callback.getMode = function twinklespeedyCallbackGetMode(form) {
var mode = Twinkle.speedy.mode.userSingleSubmit;
if (form.tag_only && !form.tag_only.checked) {
if (form.delmultiple.checked) {
mode = Twinkle.speedy.mode.sysopMultipleSubmit;
} else {
mode = Twinkle.speedy.mode.sysopSingleSubmit;
}
} else {
if (form.multiple.checked) {
mode = Twinkle.speedy.mode.userMultipleSubmit;
} else {
mode = Twinkle.speedy.mode.userSingleSubmit;
}
}
if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
mode++;
}
return mode;
};
Twinkle.speedy.callback.modeChanged = function twinklespeedyCallbackModeChanged(form) {
var namespace = mw.config.get('wgNamespaceNumber');
// first figure out what mode we're in
var mode = Twinkle.speedy.callback.getMode(form);
var isSysopMode = Twinkle.speedy.mode.isSysop(mode);
if (isSysopMode) {
$('[name=delete_options]').show();
$('[name=tag_options]').hide();
$('button.tw-speedy-submit').text(conv({ hans: '删除页面', hant: '刪除頁面' }));
} else {
$('[name=delete_options]').hide();
$('[name=tag_options]').show();
$('button.tw-speedy-submit').text(conv({ hans: '标记页面', hant: '標記頁面' }));
}
var work_area = new Morebits.quickForm.element({
type: 'div',
name: 'work_area'
});
if (mode === Twinkle.speedy.mode.userMultipleRadioClick || mode === Twinkle.speedy.mode.sysopMultipleRadioClick) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
work_area.append({
type: 'div',
label: conv({ hans: '当选择完成后,单击:', hant: '當選擇完成後,點擊:' })
});
work_area.append({
type: 'button',
name: 'submit-multiple',
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: function(event) {
Twinkle.speedy.callback[evaluateType](event);
event.stopPropagation();
}
});
}
var radioOrCheckbox = Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio';
if (isSysopMode && !Twinkle.speedy.mode.isMultiple(mode)) {
work_area.append({ type: 'header', label: conv({ hans: '自定义理由', hant: '自訂理由' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) });
}
switch (namespace) {
case 0: // article and pseudo namespace
work_area.append({ type: 'header', label: conv({ hans: '条目', hant: '條目' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.articleList, mode) });
if (/^(MOS|LTA):/.test(mw.config.get('wgPageName')) && !Morebits.isPageRedirect()) { // pseudo namespace
work_area.append({ type: 'header', label: conv({ hans: '伪命名空间', hant: '偽命名空間' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.pseudoNSList, mode) });
}
break;
case 2: // user
work_area.append({ type: 'header', label: conv({ hans: '用户页', hant: '使用者頁面' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.userList, mode) });
break;
case 3: // user talk
if (mw.util.isIPAddress(mw.config.get('wgRelevantUserName'))) {
work_area.append({ type: 'header', label: conv({ hans: '用户讨论页', hant: '使用者討論頁' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.usertalkList, mode) });
}
break;
case 6: // file
work_area.append({ type: 'header', label: conv({ hans: '文件', hant: '檔案' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.fileList, mode) });
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append({ type: 'div', label: conv({ hans: '标记CSD F3、F4、F6、F8、F9、F10,请使用Twinkle的“图权”功能。', hant: '標記CSD F3、F4、F6、F8、F9、F10,請使用Twinkle的「圖權」功能。' }) });
}
break;
case 14: // category
work_area.append({ type: 'header', label: conv({ hans: '分类', hant: '分類' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryList, mode) });
break;
case 118: // draft
work_area.append({ type: 'header', label: '草稿' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.draftList, mode) });
break;
default:
break;
}
// custom rationale lives under general criteria when tagging
var generalCriteria = Twinkle.speedy.generalList;
if (!Twinkle.speedy.mode.isSysop(mode)) {
generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
}
work_area.append({ type: 'header', label: conv({ hans: '常规', hant: '常規' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append({ type: 'div', label: conv({ hans: '标记CSD G16,请使用Twinkle的“侵权”功能。', hant: '標記CSD G16,請使用Twinkle的「侵權」功能。' }) });
}
if (mw.config.get('wgIsRedirect') || Morebits.userIsSysop) {
work_area.append({ type: 'header', label: '重定向' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) });
}
var old_area = Morebits.quickForm.getElements(form, 'work_area')[0];
form.replaceChild(work_area.render(), old_area);
// if sysop, check if CSD is already on the page and fill in custom rationale
if (isSysopMode && Twinkle.speedy.hasCSD) {
var customOption = $('input[name=csd][value=reason]')[0];
if (customOption) {
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
// force listeners to re-init
customOption.click();
customOption.parentNode.appendChild(customOption.subgroup);
}
customOption.subgroup.querySelector('input').value = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
}
}
// enlarge G11 radio/checkbox and its label
if (document.querySelector('input[value="g11"]') && Twinkle.getPref('enlargeG11Input')) {
document.querySelector('input[value="g11"]').style = 'height: 2em; width: 2em; height: -moz-initial; width: -moz-initial; -moz-transform: scale(2); -o-transform: scale(2);';
document.querySelector('input[value="g11"]').labels[0].style = 'font-size: 1.5em; line-height: 1.5em;';
}
if (!isSysopMode && mw.config.get('wgPageContentModel') !== 'wikitext') {
$('[name=tag_options]').hide();
$('[name=work_area]').empty();
var message = [
conv({ hans: 'Twinkle不支持在页面内容模型为', hant: 'Twinkle不支援在頁面內容模型為' }),
mw.config.get('wgPageContentModel'),
conv({ hans: '的页面上挂上快速删除模板,请参见', hant: '的頁面上掛上快速刪除模板,請參見' }),
$('<a>').attr({ target: '_blank', href: mw.util.getUrl('WP:SPECIALSD') }).text(conv({ hans: '手动放置模板时的注意事项', hant: '手動放置模板時的注意事項' }))[0],
'。'
];
$('[name=work_area]').append(message);
Morebits.simpleWindow.setButtonsEnabled(false);
} else {
Morebits.simpleWindow.setButtonsEnabled(true);
}
};
Twinkle.speedy.callback.priorDeletionCount = function () {
var query = {
action: 'query',
format: 'json',
list: 'logevents',
letype: 'delete',
leaction: 'delete/delete', // Just pure page deletion, no redirect overwrites or revdel
letitle: mw.config.get('wgPageName'),
leprop: '', // We're just counting we don't actually care about the entries
lelimit: 5 // A little bit goes a long way
};
new Morebits.wiki.api(conv({ hans: '检查之前的删除', hant: '檢查之前的刪除' }), query, function (apiobj) {
var response = apiobj.getResponse();
var delCount = response.query.logevents.length;
if (delCount) {
var message = conv({ hans: '被删除', hant: '被刪除' });
if (response.continue) {
message += conv({ hans: '超过', hant: '超過' });
}
message += delCount + '次';
// 3+ seems problematic
if (delCount >= 3) {
$('#prior-deletion-count').css('color', 'red');
}
// Provide a link to page logs (CSD templates have one for sysops)
var link = Morebits.htmlNode('a', conv({ hans: '(日志)', hant: '(日誌)' }));
link.setAttribute('href', mw.util.getUrl('Special:Log', {page: mw.config.get('wgPageName')}));
link.setAttribute('target', '_blank');
$('#prior-deletion-count').text(message); // Space before log link
$('#prior-deletion-count').append(link);
}
}).post();
};
Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
// mode switches
var isSysopMode = Twinkle.speedy.mode.isSysop(mode);
var multiple = Twinkle.speedy.mode.isMultiple(mode);
var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);
var openSubgroupHandler = function(e) {
$(e.target.form).find('input').prop('disabled', true);
$(e.target.form).children().css('color', 'gray');
$(e.target).parent().css('color', 'black').find('input').prop('disabled', false);
$(e.target).parent().find('input:text')[0].focus();
e.stopPropagation();
};
var submitSubgroupHandler = function(e) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
Twinkle.speedy.callback[evaluateType](e);
e.stopPropagation();
};
return $.map(list, function(critElement) {
var criterion = $.extend({}, critElement);
if (multiple) {
if (criterion.hideWhenMultiple) {
return null;
}
if (criterion.hideSubgroupWhenMultiple) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenSingle) {
return null;
}
if (criterion.hideSubgroupWhenSingle) {
criterion.subgroup = null;
}
}
if (isSysopMode) {
if (criterion.hideWhenSysop) {
return null;
}
if (criterion.hideSubgroupWhenSysop) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenUser) {
return null;
}
if (criterion.hideSubgroupWhenUser) {
criterion.subgroup = null;
}
}
if (mw.config.get('wgIsRedirect') && criterion.hideWhenRedirect) {
return null;
}
if (criterion.showInNamespaces && criterion.showInNamespaces.indexOf(mw.config.get('wgNamespaceNumber')) < 0) {
return null;
} else if (criterion.hideInNamespaces && criterion.hideInNamespaces.indexOf(mw.config.get('wgNamespaceNumber')) > -1) {
return null;
}
if (criterion.subgroup && !hasSubmitButton) {
if ($.isArray(criterion.subgroup)) {
criterion.subgroup.push({
type: 'button',
name: 'submit',
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: submitSubgroupHandler
});
} else {
criterion.subgroup = [
criterion.subgroup,
{
type: 'button',
name: 'submit', // ends up being called "csd.submit" so this is OK
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: submitSubgroupHandler
}
];
}
// FIXME: does this do anything?
criterion.event = openSubgroupHandler;
}
if (isSysopMode) {
var originalEvent = criterion.event;
criterion.event = function(e) {
if (multiple) {
return originalEvent(e);
}
var normalizedCriterion = Twinkle.speedy.normalizeHash[e.target.value];
$('[name=openusertalk]').prop('checked',
Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf(normalizedCriterion) !== -1
);
if (originalEvent) {
return originalEvent(e);
}
};
}
return criterion;
});
};
Twinkle.speedy.customRationale = [
{
label: conv({ hans: '自定义理由' + (Morebits.userIsSysop ? '(自定义删除理由)' : ''), hant: '自訂理由' + (Morebits.userIsSysop ? '(自訂刪除理由)' : '') }),
value: 'reason',
tooltip: conv({ hans: '该页至少应该符合一条快速删除的标准,并且您必须在理由中提到。这不是万能的删除理由。', hant: '該頁至少應該符合一條快速刪除的標準,並且您必須在理由中提到。這不是萬能的刪除理由。' }),
subgroup: {
name: 'reason_1',
type: 'input',
label: '理由:',
size: 60
}
// hideWhenMultiple: true
}
];
Twinkle.speedy.pseudoNSList = [
{
label: conv({ hans: 'O8. 在伪命名空间中创建的非重定向页', hant: 'O8. 在偽命名空間中建立的非重新導向頁面' }),
value: 'o8',
tooltip: conv({ hans: '伪命名空间仅能用于重定向。如可以移动到合适的名称,请将页面移动到合适的名称,否则请使用此款快速删除。若页面明显是一个条目,则不适用此款快速删除。', hant: '偽命名空間僅能用於重新導向。如可以移動到合適的名稱,請將頁面移動到合適的名稱,否則請使用此款快速刪除。若頁面明顯是一個條目,則不適用此款快速刪除。' })
}
];
Twinkle.speedy.fileList = [
{
label: conv({ hans: 'F1: 重复的文件(完全相同或缩小),而且不再被条目使用', hant: 'F1: 重複的檔案(完全相同或縮小),而且不再被條目使用' }),
value: 'f1',
subgroup: {
name: 'f1_filename',
type: 'input',
label: conv({ hans: '与此文件相同的文件名:', hant: '與此檔案相同的檔名:' }),
tooltip: conv({ hans: '可不含“File:”前缀。', hant: '可不含「File:」字首。' })
}
},
{
label: conv({ hans: 'F3: 来源不明的文件', hant: 'F3: 來源不明的檔案' }),
value: 'f3',
hideWhenUser: true
},
{
label: conv({ hans: 'F4: 未知著作权或著作权无法被查证的文件', hant: 'F4: 未知著作權或著作權無法被查證的檔案' }),
value: 'f4',
hideWhenUser: true
},
{
label: conv({ hans: 'F5: 被高清晰度或SVG文件取代的图片', hant: 'F5: 被高解析度或SVG檔案取代的圖片' }),
value: 'f5',
subgroup: {
name: 'f5_filename',
type: 'input',
label: conv({ hans: '新文件名:', hant: '新檔名:' }),
tooltip: conv({ hans: '可不含“File:”前缀。', hant: '可不含「File:」字首。' })
}
},
{
label: conv({ hans: 'F6: 没有被条目使用的非自由著作权文件', hant: 'F6: 沒有被條目使用的非自由著作權檔案' }),
value: 'f6',
hideWhenUser: true
},
{
label: conv({ hans: 'F7: 与维基共享资源文件重复的文件', hant: 'F7: 與維基共享資源檔案重複的檔案' }),
value: 'f7',
subgroup: {
name: 'f7_filename',
type: 'input',
label: conv({ hans: '维基共享资源上的文件名:', hant: '維基共享資源上的檔名:' }),
value: Morebits.pageNameNorm,
tooltip: conv({ hans: '如与本文件名相同则可留空,可不含“File:”前缀。', hant: '如與本檔名相同則可留空,可不含「File:」字首。' })
},
hideWhenMultiple: true
},
{
label: conv({ hans: 'F8: 明显侵权之文件', hant: 'F8: 明顯侵權之檔案' }),
value: 'f8',
hideWhenUser: true
},
{
label: conv({ hans: 'F9: 没有填写任何合理使用依据的非自由著作权文件', hant: 'F9: 沒有填寫任何合理使用依據的非自由著作權檔案' }),
value: 'f9',
hideWhenUser: true
},
{
label: conv({ hans: 'F10: 可被替代的非自由著作权文件', hant: 'F10: 可被替代的非自由著作權檔案' }),
value: 'f10',
hideWhenUser: true
}
];
Twinkle.speedy.articleList = [
{
label: conv({ hans: 'A1: 内容空泛(包括但不限于没有定义)。', hant: 'A1: 內容空泛(包括但不限於沒有定義)。' }),
value: 'a1',
tooltip: conv({ hans: '条目的内容笼统,或甚至根本没有提及条目主体,使条目不能用以区分其他事物。例如:“他是一个很有趣的人,他创建了工厂和庄园。并且,顺便提一下,他的妻子也很好。”<br>“内容空泛”与“没有实际内容”的分别在于:后者乃是与主题完全无关,或是不知所云;前者可以与主题有一定关系,但没有明确描述主题(包括但不限于没有对主题作基本定义);前者同时包含后者。', hant: '條目的內容籠統,或甚至根本沒有提及條目主體,使條目不能用以區分其他事物。例如:「他是一個很有趣的人,他建立了工廠和莊園。並且,順便提一下,他的妻子也很好。」<br>「內容空泛」與「沒有實際內容」的分別在於:後者乃是與主題完全無關,或是不知所云;前者可以與主題有一定關係,但沒有明確描述主題(包括但不限於沒有對主題作基本定義);前者同時包含後者。' })
},
{
label: conv({ hans: 'A2: 内容只包括外部链接、参见、图书参考、分类、模板、跨语言链接的条目', hant: 'A2: 內容只包括外部連結、參見、圖書參考、分類、模板、跨語言連結的條目' }),
value: 'a2',
tooltip: conv({ hans: '请注意:有些维基人创建条目时会分开多次保存,请避免删除有人正在编辑的页面。<br>带有{{inuse}}模板的不适用。', hant: '請注意:有些維基人建立條目時會分開多次儲存,請避免刪除有人正在編輯的頁面。<br>帶有{{inuse}}模板的不適用。' })
},
{
label: conv({ hans: 'A3: 复制自其他中文维基计划,或是与其他中文维基计划内容相同的文章。', hant: 'A3: 複製自其他中文維基計劃,或是與其他中文維基計劃內容相同的文章。' }),
value: 'a3',
subgroup: {
name: 'a3_pagename',
type: 'input',
label: conv({ hans: '现有条目名:', hant: '現有條目名:' }),
tooltip: conv({ hans: '请加上跨 wiki 前缀。不自动加上链接,若需要请自行加上[[]]。', hant: '請加上跨 wiki 字首。不自動加上連結,若需要請自行加上[[]]。' }),
size: 60
}
},
{
label: conv({ hans: 'A6: 复制自其他维基百科语言版本,且完全没有翻译。', hant: 'A6: 複製自其他維基百科語言版本,且完全沒有翻譯。' }),
value: 'a6',
tooltip: conv({ hans: '如果并不是复制于任何其他的维基百科语言版本,请换用{{notmandarin}}。<br>带有{{inuse}}和{{translating}}模板的不适用。', hant: '如果並不是複製於任何其他的維基百科語言版本,請換用{{notmandarin}}。<br>帶有{{inuse}}和{{translating}}模板的不適用。' }),
subgroup: {
name: 'a6_pagename',
type: 'input',
label: conv({ hans: '现有条目名:', hant: '現有條目名:' }),
tooltip: conv({ hans: '请加上跨 wiki 前缀。不自动加上链接,若需要请自行加上[[]]。', hant: '請加上跨 wiki 字首。不自動加上連結,若需要請自行加上[[]]。' }),
size: 60
}
}
];
Twinkle.speedy.categoryList = [
{
label: conv({ hans: 'O4: 空的分类(没有条目也没有子分类)。', hant: 'O4: 空的分類(沒有條目也沒有子分類)。' }),
value: 'o4',
tooltip: conv({ hans: '不适用于Category:不要删除的分类中的空分类。', hant: '不適用於Category:不要刪除的分類中的空分類。' })
}
];
Twinkle.speedy.draftList = [
{
label: conv({ hans: 'O7: 废弃草稿。', hant: 'O7: 廢棄草稿。' }),
value: 'o7',
tooltip: conv({ hans: '任何六个月内无编辑的草稿。', hant: '任何六個月內無編輯的草稿。' })
}
];
Twinkle.speedy.userList = [
{
label: conv({ hans: 'O1: 用户请求删除自己的用户页或其子页面。', hant: 'O1: 使用者請求刪除自己的使用者頁面或其子頁面。' }),
value: 'o1',
tooltip: conv({ hans: '除了自己的用户页,只要是移动而来的页面,皆须附有合理原因。', hant: '除了自己的使用者頁面,只要是移動而來的頁面,皆須附有合理原因。' })
}
];
Twinkle.speedy.usertalkList = [
{
label: conv({ hans: 'O3: 已超过一个月未有编辑动作的匿名(IP)用户的用户讨论页', hant: 'O3: 已超過一個月未有編輯動作的匿名(IP)使用者的使用者討論頁' }),
value: 'o3',
tooltip: conv({ hans: '避免给使用同一IP地址的用户带来混淆。<br>不适用于用户讨论页的存档页面。', hant: '避免給使用同一IP位址的使用者帶來混淆。<br>不適用於使用者討論頁的存檔頁面。' })
}
];
Twinkle.speedy.generalList = [
{
label: conv({ hans: 'G1: 没有实际内容的页面', hant: 'G1: 沒有實際內容的頁面' }),
value: 'g1',
tooltip: conv({ hans: '如“adfasddd”。参见Wikipedia:胡言乱语。但注意:图片也算是内容。', hant: '如「adfasddd」。參見Wikipedia:胡言亂語。但注意:圖片也算是內容。' }),
hideInNamespaces: [ 2, 3 ] // user, user talk
},
{
label: conv({ hans: 'G2: 测试页面', hant: 'G2: 測試頁面' }),
value: 'g2',
tooltip: conv({ hans: '例如:“这是一个测试。”', hant: '例如:「這是一個測試。」' }),
hideInNamespaces: [ 2, 3 ] // user, user talk
},
{
label: conv({ hans: 'G3: 纯粹破坏,包括但不限于明显的恶作剧、错误信息、人身攻击等', hant: 'G3: 純粹破壞,包括但不限於明顯的惡作劇、錯誤資訊、人身攻擊等' }),
value: 'g3',
tooltip: conv({ hans: '包括明显的错误信息、明显的恶作剧、信息明显错误的图片,以及清理移动破坏时留下的重定向。', hant: '包括明顯的錯誤資訊、明顯的惡作劇、資訊明顯錯誤的圖片,以及清理移動破壞時留下的重新導向。' })
},
{
label: conv({ hans: 'G5: 曾经根据页面存废讨论<s>、侵权审核</s>或文件存废讨论结果删除后又重新创建的内容,而有关内容与已删除版本相同或非常相似,无论标题是否相同', hant: 'G5: 曾經根據頁面存廢討論<s>、侵權審核</s>或檔案存廢討論結果刪除後又重新建立的內容,而有關內容與已刪除版本相同或非常相似,無論標題是否相同' }),
value: 'g5',
tooltip: conv({ hans: '该内容之前必须是经存废讨论删除。<br>如该内容之前属于快速删除,请以相同理由重新提送快速删除。<br>该内容如与被删除的版本明显不同,而提删者认为需要删除,请交到存废讨论,如果提删者对此不肯定,请先联系上次执行删除的管理人员。<br>不适用于根据存废复核结果被恢复的内容。在某些情况下,重新创建的条目有机会发展,那么不应提交快速删除,而应该提交存废复核或存废讨论重新评核。', hant: '該內容之前必須是經存廢討論刪除。<br>如該內容之前屬於快速刪除,請以相同理由重新提送快速刪除。<br>該內容如與被刪除的版本明顯不同,而提刪者認為需要刪除,請交到存廢討論,如果提刪者對此不肯定,請先聯絡上次執行刪除的管理人員。<br>不適用於根據存廢覆核結果被恢復的內容。在某些情況下,重新建立的條目有機會發展,那麼不應提交快速刪除,而應該提交存廢覆核或存廢討論重新評核。' }),
subgroup: [
{
name: 'g5_1',
type: 'input',
label: conv({ hans: '删除讨论位置:', hant: '刪除討論位置:' }),
size: 60
},
{
type: 'div',
label: conv({ hans: '对于侵权页面,请使用Twinkle的“侵权”功能。', hant: '對於侵權頁面,請使用Twinkle的「侵權」功能。' })
}
],
hideSubgroupWhenMultiple: true
},
{
label: conv({ hans: 'G8: 因技术原因删除页面', hant: 'G8: 因技術原因刪除頁面' }),
value: 'g8',
tooltip: conv({ hans: '包括解封用户后删除用户页、因用户夺取而删除、删除无用的MediaWiki页面、因移动请求而删除页面、以改写删除重定向。', hant: '包括解封使用者後刪除使用者頁面、因使用者奪取而刪除、刪除無用的MediaWiki頁面、因移動請求而刪除頁面、以覆寫刪除重新導向。' }),
hideWhenUser: true
},
{
label: conv({ hans: 'G10: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: 'G10: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' }),
value: 'g10',
tooltip: conv({ hans: '提请须出于善意,并附有合理原因。', hant: '提請須出於善意,並附有合理原因。' }),
subgroup: {
name: 'g10_rationale',
type: 'input',
label: conv({ hans: '可选的解释:', hant: '可選的解釋:' }),
tooltip: conv({ hans: '比如作者在哪里请求了删除。', hant: '比如作者在哪裡請求了刪除。' }),
size: 60
},
hideSubgroupWhenSysop: true
},
{
label: conv({ hans: 'G11: 明显的广告宣传页面,或只有相关人物或团体的联系方法的页面', hant: 'G11: 明顯的廣告宣傳頁面,或只有相關人物或團體的聯絡方法的頁面' }),
value: 'g11',
tooltip: conv({ hans: '页面只收宣传之用,并须完全重写才能贴合百科全书要求。须注意,仅仅以某公司或产品为主题的条目,并不直接导致其自然满足此速删标准。<br>即便该页面具有宣传情况,除非您可以非常确定该页面创建仅为广告宣传而建,否则应以关注度提报或提删替代。', hant: '頁面只收宣傳之用,並須完全重寫才能貼合百科全書要求。須注意,僅僅以某公司或產品為主題的條目,並不直接導致其自然滿足此速刪標準。<br>即便該頁面具有宣傳情況,除非您可以非常確定該頁面建立僅為廣告宣傳而建,否則應以關注度提報或提刪替代。' })
},
{
label: conv({ hans: 'G12: 未列明可靠来源且语调负面的生者传记', hant: 'G12: 未列明可靠來源且語調負面的生者傳記' }),
value: 'g12',
tooltip: conv({ hans: '“列明”指至少一个列出的来源可直接支撑条目中的任何信息,并与其中的断言相匹配。<br>如有用户对条目中列出的来源是否属于可靠来源提出合理异议,则应交由存废讨论处理。<br>注意是未列明可靠来源且语调负面,须2项均符合方适用此项。', hant: '「列明」指至少一個列出的來源可直接支撐條目中的任何資訊,並與其中的斷言相匹配。<br>如有使用者對條目中列出的來源是否屬於可靠來源提出合理異議,則應交由存廢討論處理。<br>注意是未列明可靠來源且語調負面,須2項均符合方適用此項。' })
},
{
label: conv({ hans: 'G13: 翻译拙劣', hant: 'G13: 翻譯拙劣' }),
value: 'g13',
tooltip: conv({ hans: '不适用于所有的讨论命名空间、草稿命名空间和用户命名空间。', hant: '不適用於所有的討論命名空間、草稿命名空間和使用者命名空間。' }),
hideInNamespaces: [ 1, 2, 3, 5, 7, 9, 11, 13, 15, 101, 118, 119, 829 ] // all talk, user, draft
},
{
label: conv({ hans: 'G14: 超过两周没有进行任何翻译的非现代标准汉语页面', hant: 'G14: 超過兩週沒有進行任何翻譯的非現代標準漢語頁面' }),
value: 'g14',
tooltip: conv({ hans: '包括所有未翻译的外语、汉语方言以及文言文。<br>此项仅适用于条目、项目、维基专题、使用说明和主题命名空间。', hant: '包括所有未翻譯的外語、漢語方言以及文言文。<br>此項僅適用於條目、計畫、維基專題、使用說明和主題命名空間。' }),
hideWhenUser: true,
showInNamespaces: [ 0, 4, 12, 100, 102 ] // main, wikipedia, help, portal, wikiproject
},
{
label: conv({ hans: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等', hant: 'G15: 孤立頁面,比如沒有主頁面的討論頁、指向空頁面的重新導向等' }),
value: 'g15',
tooltip: conv({ hans: '包括以下几种类型:<br>1. 没有对应文件的文件页面;<br>2. 没有对应母页面的子页面,用户页子页面除外;<br>3. 指向不存在页面的重定向;<br>4. 没有对应内容页面的讨论页,讨论页存档和用户讨论页除外;<br>5. 不存在注册用户的用户页及用户页子页面,localhost对应IP用户的用户页和随用户更名产生的用户页重定向除外。<br>请在删除时注意有无将内容移至他处的必要。<br>不包括在主页面挂有{{CSD Placeholder}}模板的讨论页。', hant: '包括以下幾種類型:<br>1. 沒有對應檔案的檔案頁面;<br>2. 沒有對應母頁面的子頁面,使用者頁面子頁面除外;<br>3. 指向不存在頁面的重新導向;<br>4. 沒有對應內容頁面的討論頁,討論頁存檔和使用者討論頁除外;<br>5. 不存在註冊使用者的使用者頁面及使用者頁面子頁面,localhost對應IP使用者的使用者頁面和隨使用者更名產生的使用者頁面重新導向除外。<br>請在刪除時注意有無將內容移至他處的必要。<br>不包括在主頁面掛有{{CSD Placeholder}}模板的討論頁。' })
},
{
label: conv({ hans: 'G17: 位于不恰当的命名空间的消歧义页面', hant: 'G17: 位於不恰當的命名空間的消歧義頁面' }),
value: 'g17',
tooltip: conv({ hans: '在提请快速删除前,请务必先检查并清理相关消歧义页面的链入。<br>此项不论页面是否引用消歧义模板或消歧义消息模板均适用,惟对消歧义模板及消歧义消息模板本身不适用。', hant: '在提請快速刪除前,請務必先檢查並清理相關消歧義頁面的連入。<br>此項不論頁面是否引用消歧義模板或消歧義訊息模板均適用,惟對消歧義模板及消歧義訊息模板本身不適用。' }),
hideInNamespaces: [ 0, 1, 2, 3, 4, 5, 118, 119 ] // main, user, project, draft and theirs talks
},
{
label: conv({ hans: 'G18: 条目或草稿创建时,内容即与其他现有条目或草稿或其历史版本的内容完全相同或非常相似,且名称不适合作为其他条目之重定向', hant: 'G18: 條目或草稿建立時,內容即與其他現有條目或草稿或其歷史版本的內容完全相同或非常相似,且名稱不適合作為其他條目之重新導向' }),
value: 'g18',
tooltip: conv({ hans: '条目或草稿创建时,首个版本的内容与当时其他现存条目或草稿或其历史版本的全部或部分内容完全相同或非常相似,且其名称不适合改为重定向,就可以提送快速删除。<br>如果名称可以作为重定向,就应直接改为重定向,不要提送快速删除。<br>如果是多个条目或草稿合并产生的新条目或草稿,不适用。<br>如果是从主条目或草稿拆分产生的条目或草稿,不适用;如有疑虑,应提送存废讨论处理。', hant: '條目或草稿建立時,首個版本的內容與當時其他現存條目或草稿或其歷史版本的全部或部分內容完全相同或非常相似,且其名稱不適合改為重新導向,就可以提送快速刪除。<br>如果名稱可以作為重新導向,就應直接改為重新導向,不要提送快速刪除。<br>如果是多個條目或草稿合併產生的新條目或草稿,不適用。<br>如果是從主條目或草稿拆分產生的條目或草稿,不適用;如有疑慮,應提送存廢討論處理。' }),
subgroup: {
name: 'g18_pagename',
type: 'input',
label: conv({ hans: '现有页面名:', hant: '現有頁面名:' }),
size: 60
},
showInNamespaces: [ 0, 2, 118 ] // main, user, draft
}
];
Twinkle.speedy.redirectList = [
{
label: conv({ hans: 'R2: 跨命名空间重定向。', hant: 'R2: 跨命名空間重新導向。' }),
value: 'r2',
tooltip: conv({ hans: '适用于条目命名空间和草稿命名空间。<br>社群同意设立的伪命名空间不适用。<br>草稿重定向速删前,请确保草稿已经完成其作用,且其历史已移动到相应的正式页面。', hant: '適用於條目命名空間和草稿命名空間。<br>社群同意設立的偽命名空間不適用。<br>草稿重新導向速刪前,請確保草稿已經完成其作用,且其歷史已移動到相應的正式頁面。' }),
showInNamespaces: [ 0, 118 ] // main, draft
},
{
label: conv({ hans: 'R3: 格式错误,或明显笔误的重定向。', hant: 'R3: 格式錯誤,或明顯筆誤的重新導向。' }),
value: 'r3',
tooltip: conv({ hans: '非一眼能看出的拼写错误和翻译或标题用字的争议应交由存废讨论处理。<br>将常见的拼写错误名称重定向至正确名称页面,可使百科用户纵使在查找文章时拼写错误,也能够找到寻求的文章。可参阅WP:重定向#何时用重定向?。<br>如重定向名称与导向目标名称(或其相关名称)仅存在合理的大小写差异及/或重定向名称为导向目标名称(或其相关名称)的ASCII字母表述的形式(例如Kurt Godel重定向至Kurt Gödel),不视为存在任何拼写错误。如有对相关大小写差异是否合理的争议,应交由存废讨论处理。<br>因类推简化字未收录至《通用规范汉字表》导致的繁简混杂情形,或系统无法自动进行繁简处理的情形,则不适用。', hant: '非一眼能看出的拼寫錯誤和翻譯或標題用字的爭議應交由存廢討論處理。<br>將常見的拼寫錯誤名稱重新導向至正確名稱頁面,可使百科使用者縱使在尋找文章時拼寫錯誤,也能夠找到尋求的文章。可參閱WP:重新導向#何時用重新導向?。<br>如重新導向名稱與導向目標名稱(或其相關名稱)僅存在合理的大小寫差異及/或重新導向名稱為導向目標名稱(或其相關名稱)的ASCII字母表述的形式(例如Kurt Godel重新導向至Kurt Gödel),不視為存在任何拼寫錯誤。如有對相關大小寫差異是否合理的爭議,應交由存廢討論處理。<br>因類推簡化字未收錄至《通用規範漢字表》導致的繁簡混雜情形,或系統無法自動進行繁簡處理的情形,則不適用。' }),
subgroup: {
name: 'r3_type',
type: 'select',
label: conv({ hans: '适用类型:', hant: '適用類別:' }),
list: [
{ label: conv({ hans: '请选择', hant: '請選擇' }), value: '' },
{ label: conv({ hans: '标题繁简混用', hant: '標題繁簡混用' }), value: '标题繁简混用。' },
{ label: conv({ hans: '消歧义使用的括号或空格错误', hant: '消歧義使用的括號或空格錯誤' }), value: '消歧义使用的括号或空格错误。' },
{ label: conv({ hans: '间隔号使用错误', hant: '間隔號使用錯誤' }), value: '间隔号使用错误。' },
{ label: conv({ hans: '标题中使用非常见的错别字', hant: '標題中使用非常見的錯別字' }), value: '标题中使用非常见的错别字。' }
]
},
hideSubgroupWhenSysop: true
},
{
label: conv({ hans: 'R5: 指向本身或循环的重定向。', hant: 'R5: 指向本身或循環的重新導向。' }),
value: 'r5',
tooltip: '如A→B→C→……→A。'
},
{
label: conv({ hans: 'R6: 移动文件而产生的重定向,且页面标题不符合文件名指引。', hant: 'R6: 移動檔案而產生的重新導向,且頁面標題不符合檔案名稱指引。' }),
value: 'r6',
showInNamespaces: [ 6 ] // file
},
{
label: conv({ hans: 'R7: 明显与导向目标所涵盖的主题无关或比导向目标所涵盖的主题更广泛的重定向。', hant: 'R7: 明顯與導向目標所涵蓋的主題無關或比導向目標所涵蓋的主題更廣泛的重新導向。' }),
value: 'r7',
tooltip: conv({ hans: '条目完全未提及重定向的名称,或重定向名称比条目主题更广泛,但条目不含有重定向名称的有效介绍。同时,重定向名称并不是条目的别名或错误拼写。有争议的情况下,应提出存废讨论。<br>如果原重定向标题可改成消歧义页(或重定向至其他消歧义页),则不适用。<br>挂有{{关注度重定向}}或{{合并重定向}}模板的页面不适用,请改为提出存废讨论。<br>如有用户对标题用字存在未解决的争议,则应交由存废讨论处理。', hant: '條目完全未提及重新導向的名稱,或重新導向名稱比條目主題更廣泛,但條目不含有重新導向名稱的有效介紹。同時,重新導向名稱並不是條目的別名或錯誤拼寫。有爭議的情況下,應提出存廢討論。<br>如果原重新導向標題可改成消歧義頁(或重新導向至其他消歧義頁),則不適用。<br>掛有{{關注度重新導向}}或{{合併重新導向}}模板的頁面不適用,請改為提出存廢討論。<br>如有使用者對標題用字存在未解決的爭議,則應交由存廢討論處理。' })
},
{
label: conv({ hans: 'R8: 带有“(消歧义)”字样,且无链入的重定向。', hant: 'R8: 帶有「(消歧義)」字樣,且無連入的重新導向。' }),
value: 'r8',
tooltip: conv({ hans: '若重定向页与导向目标页同样带有“(消歧义)”字样,且两者的标题仅存在繁简/地区词差异,则不适用。<br在提请快速删除前,请务必先检查并清理(如适用)相关重定向的链入。<br>如有用户对应否使用消歧义及消歧义的方式存在未解决的争议,则应交由存废讨论处理。', hant: '若重新導向頁面與導向目標頁同樣帶有「(消歧義)」字樣,且兩者的標題僅存在繁簡/地區詞差異,則不適用。<br在提請快速刪除前,請務必先檢查並清理(如適用)相關重新導向的連入。<br>如有使用者對應否使用消歧義及消歧義的方式存在未解決的爭議,則應交由存廢討論處理。' })
}
];
Twinkle.speedy.normalizeHash = {
'reason': 'db',
'multiple': 'multiple',
'multiple-finish': 'multiple-finish',
'g1': 'g1',
'g2': 'g2',
'g3': 'g3',
'g5': 'g5',
'g8': 'g8',
'g10': 'g10',
'g11': 'g11',
'g12': 'g12',
'g13': 'g13',
'g14': 'g14',
'g15': 'g15',
'g16': 'g16',
'g17': 'g17',
'g18': 'g18',
'a1': 'a1',
'a2': 'a2',
'a3': 'a3',
'a6': 'a6',
'r2': 'r2',
'r3': 'r3',
'r5': 'r5',
'r6': 'r6',
'r7': 'r7',
'r8': 'r8',
'f1': 'f1',
'f3': 'f3',
'f4': 'f4',
'f5': 'f5',
'f6': 'f6',
'f7': 'f7',
'o1': 'o1',
'o3': 'o3',
'o4': 'o4',
'o7': 'o7',
'o8': 'o8'
};
Twinkle.speedy.callbacks = {
getTemplateCodeAndParams: function(params) {
var code, parameters, i;
if (params.normalizeds.length > 1) {
code = '{{delete';
params.utparams = {};
$.each(params.normalizeds, function(index, norm) {
if (norm !== 'db') {
code += '|' + norm.toUpperCase();
}
parameters = params.templateParams[index] || [];
for (var i in parameters) {
if (typeof parameters[i] === 'string') {
code += '|' + parameters[i];
}
}
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
});
code += '}}';
} else {
parameters = params.templateParams[0] || [];
code = '{{delete';
if (params.values[0] !== 'reason') {
code += '|' + params.values[0];
}
for (i in parameters) {
if (typeof parameters[i] === 'string') {
code += '|' + parameters[i];
}
}
code += '}}';
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
}
return [code, params.utparams];
},
parseWikitext: function(title, wikitext, callback) {
var query = {
action: 'parse',
prop: 'text',
pst: 'true',
text: wikitext,
contentmodel: 'wikitext',
title: title
};
var statusIndicator = new Morebits.status(conv({ hans: '构造删除理由', hant: '構造刪除理由' }));
var api = new Morebits.wiki.api(conv({ hans: '解析删除模板', hant: '解析刪除模板' }), query, function (apiObj) {
var reason = decodeURIComponent($(apiObj.getXML().querySelector('text').childNodes[0].nodeValue).find('#delete-reason').text().replace(/\+/g, ' '));
if (!reason) {
statusIndicator.warn(conv({ hans: '未能从删除模板生成删除理由', hant: '未能從刪除模板生成刪除理由' }));
} else {
statusIndicator.info('完成');
}
callback(reason);
}, statusIndicator);
api.post();
},
sysop: {
main: function(params) {
var reason;
if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
reason = prompt(conv({ hans: '输入删除理由:', hant: '輸入刪除理由:' }), '');
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
} else {
var code = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params)[0];
Twinkle.speedy.callbacks.parseWikitext(mw.config.get('wgPageName'), code, function(reason) {
if (params.promptForSummary) {
reason = prompt(conv({ hans: '输入删除理由,或单击确定以接受自动生成的:', hant: '輸入刪除理由,或點擊確定以接受自動生成的:' }), reason);
}
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
});
}
},
deletePage: function(reason, params) {
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '删除页面', hant: '刪除頁面' }));
if (reason === null) {
return Morebits.status.error(conv({ hans: '询问理由', hant: '詢問理由' }), conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
} else if (!reason || !reason.replace(/^\s*/, '').replace(/\s*$/, '')) {
return Morebits.status.error(conv({ hans: '询问理由', hant: '詢問理由' }), conv({ hans: '你不给我理由…我就…不管了…', hant: '你不給我理由…我就…不管了…' }));
}
var deleteMain = function() {
thispage.setEditSummary(reason);
thispage.setChangeTags(Twinkle.changeTags);
thispage.setWatchlist(params.watch);
thispage.deletePage(function() {
thispage.getStatusElement().info('完成');
Twinkle.speedy.callbacks.sysop.deleteTalk(params);
});
};
// look up initial contributor. If prompting user for deletion reason, just display a link.
// Otherwise open the talk page directly
if (params.openUserTalk) {
thispage.setCallbackParameters(params);
thispage.lookupCreation(function() {
Twinkle.speedy.callbacks.sysop.openUserTalkPage(thispage);
deleteMain();
});
} else {
deleteMain();
}
},
deleteTalk: function(params) {
// delete talk page
if (params.deleteTalkPage &&
params.normalized !== 'f7' &&
params.normalized !== 'o1' &&
!document.getElementById('ca-talk').classList.contains('new')) {
var talkpage = new Morebits.wiki.page(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber') + 1] + ':' + mw.config.get('wgTitle'), conv({ hans: '删除讨论页', hant: '刪除討論頁' }));
talkpage.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 已删除页面“' + Morebits.pageNameNorm + '”的讨论页');
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.deletePage();
// this is ugly, but because of the architecture of wiki.api, it is needed
// (otherwise success/failure messages for the previous action would be suppressed)
window.setTimeout(function() {
Twinkle.speedy.callbacks.sysop.deleteRedirects(params);
}, 1800);
} else {
Twinkle.speedy.callbacks.sysop.deleteRedirects(params);
}
},
deleteRedirects: function(params) {
// delete redirects
if (params.deleteRedirects) {
var query = {
action: 'query',
titles: mw.config.get('wgPageName'),
prop: 'redirects',
rdlimit: 5000 // 500 is max for normal users, 5000 for bots and sysops
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '获取重定向列表…', hant: '取得重新導向列表…' }), query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
new Morebits.status(conv({ hans: '删除重定向', hant: '刪除重新導向' })));
wikipedia_api.params = params;
wikipedia_api.post();
}
// prompt for protect on G11
var $link, $bigtext;
if (params.normalized === 'g11') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里施行保护', hant: '點擊這裡施行保護' }),
css: { fontSize: '130%', fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
mw.config.set('wgArticleId', 0);
Twinkle.protect.callback();
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '白纸保护该页', hant: '白紙保護該頁' }),
css: { fontSize: '130%', fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
}
// promote Unlink tool
if (mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f7') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里前往取消链入工具', hant: '點擊這裡前往取消連入工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback(conv({ hans: '取消对已删除文件 ', hant: '取消對已刪除檔案 ' }) + Morebits.pageNameNorm + ' 的使用');
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '取消对已删除文件的使用', hant: '取消對已刪除檔案的使用' }),
css: { fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else if (params.normalized !== 'f7') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里前往取消链入工具', hant: '點擊這裡前往取消連入工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback(conv({ hans: '取消对已删除页面 ', hant: '取消對已刪除頁面 ' }) + Morebits.pageNameNorm + conv({ hans: ' 的链接', hant: ' 的連結' }));
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '取消对已删除页面的链接', hant: '取消對已刪除頁面的連結' }),
css: { fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
}
$link = $('<a>', {
href: mw.util.getUrl('Special:RandomInCategory/快速删除候选'),
text: conv({ hans: '单击前往下一个快速删除候选', hant: '點擊前往下一個快速刪除候選' })
});
Morebits.status.info('工具', $link[0]);
},
openUserTalkPage: function(pageobj) {
pageobj.getStatusElement().unlink(); // don't need it anymore
var user = pageobj.getCreator();
var params = pageobj.getCallbackParameters();
var query = {
title: 'User talk:' + user,
action: 'edit',
preview: 'yes',
vanarticle: Morebits.pageNameNorm
};
if (params.normalized === 'db' || Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(params.normalized) !== -1) {
// provide a link to the user talk page
var $link, $bigtext;
$link = $('<a/>', {
href: mw.util.wikiScript('index') + '?' + $.param(query),
text: conv({ hans: '点此打开User talk:', hant: '點此打開User talk:' }) + user,
target: '_blank',
css: { fontSize: '130%', fontWeight: 'bold' }
});
$bigtext = $('<span/>', {
text: conv({ hans: '通知页面创建者', hant: '通知頁面建立者' }),
css: { fontSize: '130%', fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else {
// open the initial contributor's talk page
var statusIndicator = new Morebits.status(conv({ hans: '打开用户', hant: '打開使用者' }) + user + conv({ hans: '的讨论页编辑窗口', hant: '的討論頁編輯視窗' }), conv({ hans: '打开中…', hant: '打開中…' }));
switch (Twinkle.getPref('userTalkPageMode')) {
case 'tab':
window.open(mw.util.wikiScript('index') + '?' + $.param(query), '_blank');
break;
case 'blank':
window.open(mw.util.wikiScript('index') + '?' + $.param(query), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
case 'window':
/* falls through */
default:
window.open(mw.util.wikiScript('index') + '?' + $.param(query),
window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
}
statusIndicator.info('完成');
}
},
deleteRedirectsMain: function(apiobj) {
var xmlDoc = apiobj.getXML();
var $snapshot = $(xmlDoc).find('redirects rd');
var total = $snapshot.length;
var statusIndicator = apiobj.statelem;
if (!total) {
statusIndicator.info(conv({ hans: '未发现重定向', hant: '未發現重新導向' }));
return;
}
statusIndicator.status('0%');
var current = 0;
var onsuccess = function(apiobjInner) {
var now = parseInt(100 * ++current / total, 10) + '%';
statusIndicator.update(now);
apiobjInner.statelem.unlink();
if (current >= total) {
statusIndicator.info(now + '(完成)');
Morebits.wiki.removeCheckpoint();
}
};
Morebits.wiki.addCheckpoint();
$snapshot.each(function(key, value) {
var title = $(value).attr('title');
var page = new Morebits.wiki.page(title, conv({ hans: '删除重定向 "', hant: '刪除重新導向 "' }) + title + '"');
page.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 重定向到已删除页面“' + Morebits.pageNameNorm + '”');
page.setChangeTags(Twinkle.changeTags);
page.deletePage(onsuccess);
});
}
},
user: {
main: function(pageobj) {
var statelem = pageobj.getStatusElement();
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
statelem.status(conv({ hans: '检查页面已有标记…', hant: '檢查頁面已有標記…' }));
// check for existing deletion tags
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|deletebecause|speedy|csd|速刪|速删|快删|快刪)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && !confirm(conv({ hans: '在页面上找到快速删除模板,要移除并加入新的吗?', hant: '在頁面上找到快速刪除模板,要移除並加入新的嗎?' }))) {
statelem.error(conv({ hans: '快速删除模板已被置于页面中。', hant: '快速刪除模板已被置於頁面中。' }));
return;
}
text = textNoSd;
var copyvio = /(?:\{\{\s*(copyvio|侵权|侵權)[^{}]*?\}\})/i.exec(text);
if (copyvio && !confirm(conv({ hans: '著作权验证模板已被置于页面中,您是否仍想加入一个快速删除模板?', hant: '著作權驗證模板已被置於頁面中,您是否仍想加入一個快速刪除模板?' }))) {
statelem.error(conv({ hans: '页面中已有著作权验证模板。', hant: '頁面中已有著作權驗證模板。' }));
return;
}
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想加入一个快速删除模板?', hant: '}}已被置於頁面中,您是否仍想加入一個快速刪除模板?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// returns => [<string> wikitext, <object> utparams]
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
code = buildData[0];
params.utparams = buildData[1];
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
// patrol the page, if reached from Special:NewPages
if (Twinkle.getPref('markSpeedyPagesAsPatrolled')) {
thispage.patrol();
}
// Wrap SD template in noinclude tags if we are in template space.
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = '<noinclude>' + code + '</noinclude>';
}
// Remove tags that become superfluous with this action
text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
if (mw.config.get('wgNamespaceNumber') === 6) {
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
if (params.requestsalt) {
code = '{{salt}}\n' + code;
}
// Generate edit summary for edit
var editsummary;
if (params.normalizeds.length > 1) {
editsummary = conv({ hans: '请求快速删除(', hant: '請求快速刪除(' });
$.each(params.normalizeds, function(index, norm) {
if (norm !== 'db') {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']]、';
}
});
editsummary = editsummary.substr(0, editsummary.length - 1); // remove trailing comma
editsummary += ')';
} else if (params.normalizeds[0] === 'db') {
editsummary = conv({ hans: '请求[[WP:CSD|快速删除]]:', hant: '請求[[WP:CSD|快速刪除]]:' }) + params.templateParams[0]['1'];
} else {
editsummary = conv({ hans: '请求快速删除', hant: '請求快速刪除' }) + '([[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']])';
}
// Blank attack pages
if (params.blank) {
text = code;
} else {
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(code + '\n', Twinkle.hatnoteRegex).getText();
}
pageobj.setPageText(text);
pageobj.setEditSummary(editsummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(params.watch);
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
},
tagComplete: function(pageobj) {
var params = pageobj.getCallbackParameters();
// Notification to first contributor
if (params.usertalk) {
var callback = function(pageobj) {
var initialContrib = pageobj.getCreator();
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
Morebits.status.warn('您(' + initialContrib + conv({ hans: ')创建了该页,跳过通知', hant: ')建立了該頁,跳過通知' }));
initialContrib = null;
// don't notify users when their user talk page is nominated
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
Morebits.status.warn(conv({ hans: '通知页面创建者:用户创建了自己的讨论页', hant: '通知頁面建立者:使用者建立了自己的討論頁' }));
initialContrib = null;
// quick hack to prevent excessive unwanted notifications. Should actually be configurable on recipient page...
} else if (initialContrib === 'A2093064-bot' && params.normalizeds[0] === 'g15') {
Morebits.status.warn(conv({ hans: '通知页面创建者:由机器人创建,跳过通知', hant: '通知頁面建立者:由機器人建立,跳過通知' }));
initialContrib = null;
} else {
var talkPageName = 'User talk:' + initialContrib;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
flowpage.setTopic('[[:' + Morebits.pageNameNorm + ']]的快速删除通知');
flowpage.setContent('{{subst:db-notice|target=' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.newTopic();
}, function() {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')'),
notifytext;
notifytext = '\n{{subst:db-notice|target=' + Morebits.pageNameNorm;
notifytext += (params.welcomeuser ? '' : '|nowelcome=yes') + '}}--~~~~';
var editsummary = '通知:';
if (params.normalizeds.indexOf('g12') === -1) { // no article name in summary for G10 deletions
editsummary += '页面[[' + Morebits.pageNameNorm + ']]';
} else {
editsummary += '一攻击性页面';
}
editsummary += '快速删除提名';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(editsummary);
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
};
var thispage = new Morebits.wiki.page(Morebits.pageNameNorm);
thispage.lookupCreation(callback);
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
},
// note: this code is also invoked from twinkleimage
// the params used are:
// for CSD: params.values, params.normalizeds (note: normalizeds is an array)
// for DI: params.fromDI = true, params.templatename, params.normalized (note: normalized is a string)
addToLog: function(params, initialContrib) {
var usl = new Morebits.userspaceLogger(Twinkle.getPref('speedyLogPageName'));
usl.initialText =
'这是该用户使用[[WP:TW|Twinkle]]的速删模块做出的[[WP:CSD|快速删除]]提名列表。\n\n' +
'如果您不再想保留此日志,请在[[' + Twinkle.getPref('configPage') + '|参数设置]]中关掉,并' +
'使用[[WP:CSD#O1|CSD O1]]提交快速删除。' +
(Morebits.userIsSysop ? '\n\n此日志并不记录用Twinkle直接执行的删除。' : '');
var appendText = '# [[:' + Morebits.pageNameNorm + ']]:';
if (params.fromDI) {
if (params.normalized === 'f3 f4') {
appendText += '图版[[WP:CSD#F3|CSD F3]]+[[WP:CSD#F4|CSD F4]]({{tl|no source no license/auto}})';
} else {
appendText += '图版[[WP:CSD#' + params.normalized.toUpperCase() + '|CSD ' + params.normalized.toUpperCase() + ']]({{tl|' + params.templatename + '}})';
}
} else {
if (params.normalizeds.length > 1) {
appendText += '多个理由(';
$.each(params.normalizeds, function(index, norm) {
appendText += '[[WP:CSD#' + norm.toUpperCase() + '|' + norm.toUpperCase() + ']]、';
});
appendText = appendText.substr(0, appendText.length - 1); // remove trailing comma
appendText += ')';
} else if (params.normalizeds[0] === 'db') {
appendText += '自定义理由';
} else {
appendText += '[[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']]';
}
}
if (params.requestsalt) {
appendText += conv({ hans: ';请求白纸保护', hant: ';請求白紙保護' });
}
if (initialContrib) {
appendText += ';通知{{user|' + initialContrib + '}}';
}
appendText += ' ~~~~~\n';
usl.changeTags = Twinkle.changeTags;
usl.log(appendText, conv({ hans: '记录对[[', hant: '記錄對[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的快速删除提名', hant: ']]的快速刪除提名' }));
}
}
};
// validate subgroups in the form passed into the speedy deletion tag
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(form, values) {
var parameters = [];
$.each(values, function(index, value) {
var currentParams = [];
var redimage;
switch (value) {
case 'reason':
if (form['csd.reason_1']) {
var dbrationale = form['csd.reason_1'].value;
if (!dbrationale || !dbrationale.trim()) {
alert(conv({ hans: '自定义理由:请指定理由。', hant: '自訂理由:請指定理由。' }));
parameters = null;
return false;
}
currentParams['1'] = dbrationale;
}
break;
case 'a3':
if (form['csd.a3_pagename'] && form['csd.a3_pagename'].value) {
currentParams.pagename = form['csd.a3_pagename'].value;
}
break;
case 'a6':
if (form['csd.a6_pagename'] && form['csd.a6_pagename'].value) {
currentParams.pagename = form['csd.a6_pagename'].value;
}
break;
case 'g5':
if (form['csd.g5_1']) {
var deldisc = form['csd.g5_1'].value;
if (deldisc) {
if (!/^(Wikipedia|WP|维基百科|維基百科):/i.test(deldisc)) {
alert(conv({ hans: 'CSD G5:您提供的讨论页名必须以“Wikipedia:”开头。', hant: 'CSD G5:您提供的討論頁名必須以「Wikipedia:」開頭。' }));
parameters = null;
return false;
}
currentParams['1'] = deldisc;
}
}
break;
case 'g10':
if (form['csd.g10_rationale'] && form['csd.g10_rationale'].value) {
currentParams.rationale = form['csd.g10_rationale'].value;
}
break;
case 'g16':
if (form['csd.g16_pagename']) {
var pagename = form['csd.g16_pagename'].value;
if (!pagename || !pagename.trim()) {
alert(conv({ hans: 'CSD G16:请提供页面名称。', hant: 'CSD G16:請提供頁面名稱。' }));
parameters = null;
return false;
}
currentParams.pagename = pagename;
}
break;
case 'g18':
if (form['csd.g18_pagename']) {
var otherpage = form['csd.g18_pagename'].value;
if (!otherpage || !otherpage.trim()) {
alert(conv({ hans: 'CSD G18:请提供现有页面的名称。', hant: 'CSD G18:請提供現有頁面的名稱。' }));
parameters = null;
return false;
}
currentParams.pagename = otherpage;
}
break;
case 'f1':
if (form['csd.f1_filename']) {
redimage = form['csd.f1_filename'].value;
if (!redimage || !redimage.trim()) {
alert(conv({ hans: 'CSD F1:请提供另一文件的名称。', hant: 'CSD F1:請提供另一檔案的名稱。' }));
parameters = null;
return false;
}
currentParams.filename = redimage.replace(new RegExp('^\\s*' + Morebits.namespaceRegex(6) + ':', 'i'), '');
}
break;
case 'f5':
if (form['csd.f5_filename']) {
redimage = form['csd.f5_filename'].value;
if (!redimage || !redimage.trim()) {
alert(conv({ hans: 'CSD F5:请提供另一文件的名称。', hant: 'CSD F5:請提供另一檔案的名稱。' }));
parameters = null;
return false;
}
currentParams.filename = redimage.replace(new RegExp('^\\s*' + Morebits.namespaceRegex(6) + ':', 'i'), '');
}
break;
case 'f7':
if (form['csd.f7_filename']) {
var filename = form['csd.f7_filename'].value;
if (filename && filename !== Morebits.pageNameNorm) {
if (filename.indexOf('Image:') === 0 || filename.indexOf('File:') === 0 ||
filename.indexOf('文件:') === 0 || filename.indexOf('檔案:') === 0) {
currentParams['1'] = filename;
} else {
currentParams['1'] = 'File:' + filename;
}
}
}
break;
case 'r3':
if (form['csd.r3_type']) {
var redirtype = form['csd.r3_type'].value;
if (!redirtype) {
alert(conv({ hans: 'CSD R3:请选择适用类型。', hant: 'CSD R3:請選擇適用類別。' }));
parameters = null;
return false;
}
currentParams['1'] = redirtype;
}
break;
default:
break;
}
parameters.push(currentParams);
});
return parameters;
};
// function for processing talk page notification template parameters
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) { // eslint-disable-line no-unused-vars
var utparams = [];
switch (normalized) {
default:
break;
}
return utparams;
};
Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
if (values.length === 0) {
alert(conv({ hans: '请选择一个理据!', hant: '請選擇一個理據!' }));
return null;
}
return values;
};
Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {
var form = e.target.form ? e.target.form : e.target;
if (e.target.type === 'checkbox' || e.target.type === 'text' ||
e.target.type === 'select') {
return;
}
var tag_only = form.tag_only;
if (tag_only && tag_only.checked) {
Twinkle.speedy.callback.evaluateUser(e);
return;
}
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
return;
}
var normalizeds = values.map(function(value) {
return Twinkle.speedy.normalizeHash[value];
});
// analyse each criterion to determine whether to watch the page, prompt for summary, or open user talk page
var watchPage, promptForSummary;
normalizeds.forEach(function(norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = Twinkle.getPref('watchSpeedyExpiry');
}
if (Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(norm) !== -1) {
promptForSummary = true;
}
});
var params = {
values: values,
normalizeds: normalizeds,
watch: watchPage,
deleteTalkPage: form.talkpage && form.talkpage.checked,
deleteRedirects: form.redirects.checked,
openUserTalk: form.openusertalk.checked,
promptForSummary: promptForSummary,
templateParams: Twinkle.speedy.getParameters(form, values)
};
if (!params.templateParams) {
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Twinkle.speedy.callbacks.sysop.main(params);
};
Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
var form = e.target.form ? e.target.form : e.target;
if (e.target.type === 'checkbox' || e.target.type === 'text' ||
e.target.type === 'select') {
return;
}
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
return;
}
// var multiple = form.multiple.checked;
var normalizeds = [];
$.each(values, function(index, value) {
var norm = Twinkle.speedy.normalizeHash[value];
normalizeds.push(norm);
});
// analyse each criterion to determine whether to watch the page/notify the creator
var watchPage = false;
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = Twinkle.getPref('watchSpeedyExpiry');
return false; // break
}
});
var notifyuser = false;
if (form.notify.checked) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
notifyuser = true;
return false; // break
}
});
}
var welcomeuser = false;
if (notifyuser) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1) {
welcomeuser = true;
return false; // break
}
});
}
var csdlog = false;
if (Twinkle.getPref('logSpeedyNominations')) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1) {
csdlog = true;
return false; // break
}
});
}
var params = {
values: values,
normalizeds: normalizeds,
watch: watchPage,
usertalk: notifyuser,
welcomeuser: welcomeuser,
lognomination: csdlog,
blank: form.blank.checked,
requestsalt: form.salting.checked,
templateParams: Twinkle.speedy.getParameters(form, values)
};
if (!params.templateParams) {
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '标记页面', hant: '標記頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
Twinkle.addInitCallback(Twinkle.speedy, 'speedy');
})(jQuery);
// </nowiki>
8322bb535f18c528d0c5d237ee87c8af309e869f
Template:Ifsubst
10
93
180
2023-12-29T20:50:36Z
zhwp>Xiplus-abot
0
已更改“[[Template:Ifsubst]]”的保护设置:高風險模板:102254引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#ifeq:{{ {{{|safesubst:}}}NAMESPACE}}{{{nosubst|}}}|{{NAMESPACE}}
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}<noinclude>
{{Documentation}}
</noinclude>
2a9e67bf7493f3014705d612ba3132ca42647826
Template:Birth date and age/doc
10
243
505
2024-01-08T02:21:01Z
zhwp>Kethyga
0
// Edit via Wikiplus
wikitext
text/x-wiki
<includeonly>
{{#ifeq:{{#titleparts:{{PAGENAME}}|1}}|Birth date and age
| {{Template shortcut|Bda}}
| {{Template shortcut|Dob}}
}}
{{#ifeq:{{#titleparts:{{PAGENAME}}|1}}|Birth date and age
| {{High-use|45,000+}} <!--(Template:Birth date and age)-->
| {{High-use|10,000+}} <!--(Template:Birth date)-->
}}</includeonly><noinclude>{{template doc page viewed directly|{{tl|Birth date and age}}和{{tl|Birth date}}}}</noinclude>
使用模板{{tl|Birth date and age}}將會顯示出生日期,並在其後自動計算並加註今年的年齡。{{tl|Birth date}}是一个用法相似的模板,但不会加注年龄。
如果知道出生日,但只欲顯示出生年份,請使用{{tl|Birth year and age confirmed}}。如果不知道出生日,只知道出生年份(含月份),請使用{{tl|Birth year and age}}。
== 使用說明 ==
{| class="plainlinksneverexpand noprint" style="margin-top:0; width:100%; text-align:center;border:1px #ddd solid;border-radius:5px;"
|-
! style="background:#dfd;border-radius:5px;"|本頁說明全部範例所使用的今天日期是<br>
{{CURRENTYEAR}}年{{CURRENTMONTHNAME}}{{CURRENTDAY}}日
|}
請使用以下原始碼:
: <code><nowiki>{{Birth date|year=|month=|day=}}</nowiki></code>
: <code><nowiki>{{Birth date and age|year=|month=|day=}}</nowiki></code>
其中:
* '''year''':出生西元年份(請填寫四位數的阿拉伯數字,不須加上「年」)
* '''month''':出生月份(請填寫阿拉伯數字,不須加上「月」)
* '''day''':出生日(請填寫阿拉伯數字,不須加上「日」)
== 範例 ==
'''例1''',使用:
<pre>{{Birth date and age|year=1993|month=2|day=24}}</pre>
页面上显示为:
{{Birth date and age|year=1993|month=2|day=24}}
'''例2''',也可以省略變數名稱,例如:
<pre>{{Birth date and age|1993|2|24}}</pre>
页面上显示为:
{{Birth date and age|1993|2|24}}
'''例3''',若使用:
<pre>{{Birth date|1993|02|24}}</pre>
则页面上显示为:
{{Birth date|1993|2|24}}
== 重定向 ==
{{tl|生日和年齡}}重定向至{{tl|Birth date and age}}。
== 参见 ==
* {{tl|Death date and age}},用于显示某人去世日期与年龄。
* {{tl|Start date and age}},傳回日期和它距離今天的時間長度。
{{出生、逝世及日期模板|BDA}}
<includeonly>{{Sandbox other||<!-- 本行下加入模板的分類 -->
[[Category:日期计算模板|{{PAGENAME}}]]
[[Category:生卒模板|{{PAGENAME}}]]
}}</includeonly>
<templatedata>
{
"params": {
"year": {
"label": "出生年份",
"description": "请填写四位数的阿拉伯数字,不须加上“年”",
"type": "number",
"required": true
},
"day": {
"label": "出生日",
"description": "请填写阿拉伯数字,不须加上“日”",
"type": "number",
"suggested": true
},
"month": {
"label": "出生月份",
"description": "请填写阿拉伯数字,不须加上“月”",
"type": "number",
"suggested": true
}
},
"description": "显示出生日期,并在其后自动计算并加注今年的年龄。如果知道出生日,但只欲显示出生年份,请使用{{Birth year and age confirmed}}。如果不知道出生日,只知道出生年份,请使用{{Birth year and age}}。",
"maps": {
"生日和年齡": {},
"生日和年齡 ": {}
},
"paramOrder": [
"year",
"day",
"month"
],
"format": "inline"
}
</templatedata>
a9efb19968a3733e12487d43bf41563ddf2cd231
Template:Userbox/doc
10
279
582
2024-01-08T18:45:44Z
zhwp>Zyksnowy
0
/* top */
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{內聯模板文件}}
{{Lua|Module:Userbox}}
{{高風險模板}}
{{缺乏中文說明}}
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
本模板適用於建置[[wikipedia:用戶框|用戶框]],提供使用者在用戶頁面顯示使用者的一些資訊,以免於HTML與Wikitable參數的麻煩。
'''[[WP:NFCC|合理使用圖像]]不得用於用戶框,任何使用者可在不經對方同意下,移除相關圖片。'''
== 使用方式 ==
<pre style="overflow: auto">-{}-
{{Userbox
|bodyclass = <!--自訂HTML Class參數-->
|border-c = <!--邊框色彩 (預設與 id-c 之參數相同)-->
|border-s = <!--邊框像素大小 (預設值:1)-->
|float = <!--流動對齊方式 left|right|none (預設值:left)-->
|id = <!--id 圖片或文字(選用,預設尺寸是x45px)-->
|id-a = <!--id 水平對齊方式 left/center/right/justify (預設:center)-->
|id-c = <!--id 的背景色彩 (預設:#d0d0d0)-->
|id-fc = <!--id 的文字色彩 (預設:black)-->
|id-h = <!--id 框的像素大小 (預設:45)-->
|id-lh = <!--id 行高 (預設:1em)-->
|id-op = <!--id 的其他 CSS 參數-->
|id-p = <!--id 的儲存格留白值 (預設:0 1px 0 0)-->
|id-s = <!--id 文字點數 (預設:14)-->
|id-w = <!--id 框長度 (預設:45)-->
|info-class = <!--Adds an HTML class attribute to the "info" HTML table-row, to allow for styling, emission of microformats, etc.-->
|info = <!--info 框圖文內容-->
|info-a = <!--info 框水平對齊方式 left/center/right/justify (預設:left)-->
|info-c = <!--info 框背景色 (預設:#e0e0e0)-->
|info-fc = <!--info 框文字色彩 (預設:black)-->
|info-lh = <!--info 框行高 (預設:1.25em)-->
|info-op = <!--info 框的其他CSS樣式參數-->
|info-p = <!--info 框的留白值 (預設:0 4px 0 4px)-->
|info-s = <!--info 文字點數 (預設:8)-->
|nocat = <!--屏蔽頁面分類 (預設:false)-->
|usercategory = <!--使用者自設分類(選用)-->
|usercategory2 = <!--使用者自設分類(選用)-->
|usercategory3 = <!--使用者自設分類(選用)-->
}}
</pre>
* 全部參數皆為選填
* 圖像建議少於45px
<!-- explain what this template's parameters do -- if no params, delete the definition -->
多数基于HTML的表格仅用这些参数的一小部分。以下子集可以用来把HTML用户框快速转换成这里所用的格式:
<pre>
{{Userbox
|border-c =
|id =
|id-c =
|id-fc =
|id-s =
|info =
|info-c =
|info-fc =
|info-lh =
|info-s =
|nocat = {{{nocat|}}}
|usercategory =
}}
</pre>
== 範例 ==
{|
!style="width: 300px;"| 代码
!效果
|-
| <pre>{{Userbox}}</pre> || {{Userbox}}
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 2
|id = foo
|id-c = #ffffee
|id-s = 20
|info = ''foo bar''
|info-c = #ffeeff
|info-s = 12
}}</pre> || {{Userbox|id=foo|id-s=20|id-c=#ffffee|info=''foo bar''|info-c=#ffeeff|info-s=12|border-c=#aaffaa|border-s=2}}
|-
| colspan="2"| 以下展示高度超过45px的用户框的默认外观,比较一下上下两个用户框的差异。
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 2
|id = foo logo
|id-c = #ffffee
|info = ''We are trying to see
default distance in between text
lines, see the distance in
between cell content and its border,
and also see total height.''
|info-c = #ffeeff
}}</pre> || {{Userbox|id=foo logo|id-c=#ffffee|info=''We are trying to see default distance in between text lines, see the distance in between cell content and its border, and also see total height.''|info-c=#ffeeff|border-c=#aaffaa|border-s=2}}
|-
| colspan="2"| 以下展示怎样能修改用户框并进一步指定参数来降低用户框的高度以达到推荐的45px,即使有四行文字。在四行文字之下,单元格边距参数info-p也可以设置成1pt 1pt 1pt 2pt,或者1pt 2pt以达到更好的效果。
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 1
|id = foo logo
|id-c = #ffffee
|id-lh = 1.1em
|id-s = 14
|info = ''We have specified values
to lessen the distance in between
text lines & padding space in between
cell content and its border.''
|info-c = #ffeeff
|info-lh = 1.05em
|info-p = 1pt
|info-s = 8
}}</pre> || {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffffee|info=''We have specified values to lessen the distance in between text lines & padding space in between cell content and its border.''|info-c=#ffeeff|info-s=8|info-p=1pt|info-lh=1.05em|border-c=#aaffaa|border-s=1}}
|-
| colspan="2"| 以下针对高级用户,展示怎样指定其他[[CSS]]属性,例如,font-family调整字体,text-align从默认参数调整对齐方式。如下所示,右边是2个用户框:上面一个是不带font-family或text-align参数;下面一个是以填写info-op参数来使用此类代码显示的。
|-
| <pre>{{Userbox
|border-c = #afa
|border-s = 2
|id = foo logo
|id-c = #ffe
|id-lh = 1.1em
|id-s = 14
|info = foo bar
|info-c = #fef
|info-op = font-family:'Courier New'; text-align:center;
|info-s = 14
}}</pre> || colspan="2"| {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffe|info=foo bar|info-c=#fef|info-s=14|border-c=#afa|border-s=2}} <br style="clear:both"> <br /> {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffe|info=foo bar|info-c=#fef|info-s=14|info-op=font-family:'Courier New'; text-align:center;|border-c=#afa|border-s=2}}
|}<!-- customize if needed to illustrate parameter use -->
== 模板数据 ==
{{TemplateDataHeader}}
<templatedata>
{
"description": "本模板適用於建置用戶框,提供使用者在用戶頁面顯示使用者的一些資訊,以免於HTML與Wikitable參數的麻煩。",
"params": {
"bodyclass": {
"label": "bodyclass",
"description": "自訂HTML Class參數",
"type": "string",
"default": "id-c"
},
"border-c": {
"label": "border-c",
"description": "邊框色彩",
"type": "string"
},
"border-s": {
"label": "border-s",
"description": "邊框像素大小",
"type": "string",
"default": "1"
},
"float": {
"label": "float",
"description": "流動對齊方式 left|right|none",
"type": "string",
"default": "left"
},
"id": {
"label": "id",
"description": "id 圖片或文字(選用)",
"type": "string",
"default": "x45px"
},
"id-a": {
"label": "id-a",
"description": "id 水平對齊方式 left/center/right/justify",
"type": "string",
"default": "center"
},
"id-c": {
"label": "id-c",
"description": "id 的背景色彩",
"type": "string",
"default": "#d0d0d0"
},
"id-fc": {
"label": "id-fc",
"description": "id 的文字色彩",
"type": "string",
"default": "black"
},
"id-h": {
"label": "id-h",
"description": "id 框的像素大小",
"type": "string",
"default": "45"
},
"id-lh": {
"label": "id-lh",
"description": "id 行高",
"type": "string",
"default": "1em"
},
"id-op": {
"label": "id-op",
"description": "id 的其他 CSS 參數",
"type": "string"
},
"id-p": {
"label": "id-p",
"description": "id 的儲存格留白值",
"type": "string",
"default": "0 1px 0 0"
},
"id-s": {
"label": "id-s",
"description": "id 文字點數",
"type": "string",
"default": "14"
},
"id-w": {
"label": "id-w",
"description": "id 框長度,單位是像素",
"type": "string",
"default": "45"
},
"info-class": {
"label": "info-class",
"description": "Adds an HTML class attribute to the “info” HTML table-row, to allow for styling, emission of microformats, etc.",
"type": "string"
},
"info": {
"label": "info",
"description": "info 框圖文內容",
"type": "string"
},
"info-a": {
"label": "info-a",
"description": "info 框水平對齊方式 left/center/right/justify",
"type": "string",
"default": "left"
},
"info-c": {
"label": "info-c",
"description": "info 框背景色",
"type": "string",
"default": "#e0e0e0"
},
"info-fc": {
"label": "info-fc",
"description": "info 框文字色彩",
"type": "string",
"default": "black"
},
"info-lh": {
"label": "info-lh",
"description": "info 框行高",
"type": "string",
"default": "1.25em"
},
"info-op": {
"label": "info-op",
"description": "info 框的其他CSS樣式參數",
"type": "string"
},
"info-p": {
"label": "info-p",
"description": "info 框的留白值",
"type": "string",
"default": "0 4px 0 4px"
},
"info-s": {
"label": "info-s",
"description": "info 文字點數",
"type": "string",
"default": "8"
},
"nocat": {
"label": "nocat",
"description": "屏蔽頁面分類",
"type": "string",
"default": "false"
},
"usercategory": {
"label": "usercategory",
"description": "使用者自設分類(選用)",
"type": "string"
},
"usercategory2": {
"label": "usercategory2",
"description": "使用者自設分類(選用)",
"type": "string"
},
"usercategory3": {
"label": "usercategory3",
"description": "使用者自設分類(選用)",
"type": "string"
}
}
}
</templatedata>
== 重定向 ==
* {{tl|用户框}}:中文名重定向。
* {{tl|User box}}、{{tl|User Box}}:为便于在{{tl|Userboxes}}中引用而创建的重定向。
== 参见 ==
* [[维基百科:用户框]]
* {{Tlx|Userbox-2}}:左右两边都有id区的用户框。
* {{Tlx|Userbox-r}}:右边有id区的用户框。
* {{Tlx|Userbox-m}}:只有id区的用户框。
* [[网页颜色]]
==微格式==
;bodyclass : This parameter is inserted into the "class" attribute for the userbox as a whole.
;info-class : This parameter is inserted into the "class" attribute for the info component.
{{请求翻译句|This template supports the addition of [[microformat]] information.}} This is done by adding "class" attributes to various data cells, indicating what kind of information is contained within. To flag a userbox as containing [[hCard]] information about a person, for example, add the following parameter:
<pre>
|bodyclass = vcard
</pre>
''or''
<pre>
|info-class = vcard
</pre>
''then'' (for example):
<pre>
|title = ... the books of <span class="fn">[[Iain Banks]]</span>
</pre>
... and so forth.
Examples include:
* [[:en:User:UBX/Iain Banks]] - person
* [[:en:Template:User Microformats]] - group (WikiProject Microformats)
* [[:en:Template:User Brum]] - place (Birmingham)
有關微格式的參數設置,請參考[[Wikipedia:專題/微格式|微格式專題]]。
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[Wikipedia:Wikidata]]) -->
[[Category:元用户框模板| ]]
}}</includeonly>
55c658a741bc9a58a5008bd0e1cd1cbaeee5b872
Template:Column-count
10
183
372
2024-01-08T20:50:38Z
zhwp>Xiplus-abot
0
已更改“[[Template:Column-count]]”的保护设置:高風險模板:100033引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<includeonly>-moz-column-count: {{{1|2}}}; -webkit-column-count: {{{1|2}}}; column-count: {{{1|2}}};</includeonly><noinclude>
{{documentation}}
</noinclude>
6dc87b32d7baf6ea66fb7b22fa8bc46cf0295095
Template:If subst
10
92
178
2024-01-08T20:51:18Z
zhwp>Xiplus-abot
0
已更改“[[Template:If subst]]”的保护设置:高風險模板:111531引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
#Redirect [[Template:Ifsubst]]
{{Redirect category shell|
{{模板重定向}}
}}
cab6ab798c451f05c48bff4c9c8d0e7174badb78
Module:Page
828
94
182
2024-01-08T20:51:28Z
zhwp>Xiplus-abot
0
已更改“[[Module:Page]]”的保护设置:高風險模板:123173引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local callAssert = require('Module:CallAssert')
local function main(frame, field)
local args, pargs = frame.args, ( frame:getParent() or {} ).args or {}
local makeTitle=args.makeTitle or pargs.makeTitle
local namespace=args.namespace or pargs.namespace or ""
local fragment=args.fragment or pargs.fragment or ""
local interwiki=args.interwiki or pargs.interwiki or ""
local page=args.page or args[1] or pargs.page or pargs[1] or ""
local id= tonumber( args.id or pargs.id )
local pn = {}
local title -- holds the result of the mw.title.xxx call
for i = 1,9 do pn[i] = args['p'..i] or pargs['p'..i] end
if not id and not mw.ustring.match( page, '%S' ) then page = nil end
if id then
title = callAssert(mw.title.new, 'mw.title.new', id)
elseif not page then
title = callAssert(mw.title.getCurrentTitle, 'getCurrentTitle')
elseif makeTitle then
title = callAssert(mw.title.makeTitle, 'makeTitle', namespace, page, fragment, interwiki)
else
title = callAssert(mw.title.new, 'mw.title.new', page, namespace)
end
local result = title[field]
if type(result) == "function" then
result = result(title, unpack(pn))
end
return tostring(result or "")
end
-- handle all errors in main
main = require('Module:Protect')(main)
local p = {}
-- main function does all the work
local meta = {}
function meta.__index(self, key)
return function(frame)
return main(frame, key)
end
end
setmetatable(p, meta)
function p.getContent(frame)
local args, pargs = frame.args, ( frame:getParent() or {} ).args or {}
local fmt = args.as or pargs.as or "pre"
local text = main(frame, "getContent")
fmt = mw.text.split( fmt, ", ?" )
for _, how in ipairs( fmt ) do
if how == "pre" then
text = table.concat{ "<pre>", text, "</pre>" }
elseif how == "expand" then
text = frame:preprocess(text)
elseif how == "nowiki" then
text = mw.text.nowiki(text)
end
end
return text
end
return p
9b70f0ff53b1c20fd8667c9f3d80167653279cc4
Module:Protect
828
112
218
2024-01-08T20:52:28Z
zhwp>Xiplus-abot
0
已更改“[[Module:Protect]]”的保护设置:高風險模板:115892引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local function processResult(options, success, ...)
if not success then
local message = tostring(... or '(no message)')
if options.removeLocation then
message = string.gsub(message, '^Module:[^:]+:%d+: ', '', 1)
end
return string.format(options.errFormat, message)
end
return ...
end
local function protect(func, errFormat, options)
if type(errFormat) == 'table' then
options = options or errFormat
errFormat = nil
end
options = mw.clone(options) or {}
options.errFormat = errFormat or options.errFormat or 'Error: %s'
if not options.raw then
options.errFormat = '<strong class="error">' .. options.errFormat .. '</strong>'
end
options.removeLocation = options.removeLocation == nil or options.removeLocation
return function (...)
return processResult(options, pcall(func, ...))
end
end
return protect
b9ef98da3f3df35e58a7136f9a9c73a12aa8b35d
Module:CallAssert
828
122
238
2024-01-08T20:58:29Z
zhwp>Xiplus-abot
0
已更改“[[Module:CallAssert]]”的保护设置:高風險模板:115539引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local function pack(...)
return {...}, select('#', ...)
end
local function mapArray(func, array, count)
local result = {}
for i = 1, count or #array do
result[i] = func(array[i])
end
return result
end
local function quote(value)
if type(value) == 'string' then
return (string.gsub(string.format('%q', value), '\\\n', '\\n')) -- Outer parentheses remove second value returned by gsub
end
local str = tostring(value)
if type(value) == 'table' and str ~= 'table' then
return '{' .. str .. '}'
end
return str
end
local function callAssert(func, funcName, ...)
local result, resultCount = pack(func(...))
if not result[1] then
local args, argsCount = pack(...)
args = mapArray(quote, args, argsCount)
local message = mw.ustring.format(
'%s(%s) failed',
funcName,
table.concat(args, ', ')
)
error(message, 2)
end
return unpack(result, 1, resultCount)
end
return callAssert
1f6b71105b007b84f1593a11438484f1ad94f68a
Template:Clear
10
131
258
2024-01-17T20:51:15Z
zhwp>Xiplus-abot
0
已更改“[[Template:Clear]]”的保护设置:高風險模板:102042引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<div style="clear:{{{1|both}}};"></div><noinclude>{{documentation}}</noinclude>
2d3fa80e4576702b6379930ebc3617f6d10e4346
Template:Plain link
10
320
665
2024-01-17T20:54:56Z
zhwp>Xiplus-abot
0
已更改“[[Template:Plain link]]”的保护设置:高風險模板:5058引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<span class="plainlinks">{{#if:{{{2|{{{NAME|{{{name|}}}}}}}}}
|[{{{1|{{{URL|{{{url}}}}}}}}} {{{2|{{{NAME|{{{name|}}}}}}}}}]
|[{{{1|{{{URL|{{{url}}}}}}}}}]
}}</span><noinclude>
{{documentation}}
</noinclude>
5e02091166ecba7958ced6d8308fc3544ca974fa
Template:Small
10
253
523
2024-01-18T20:51:32Z
zhwp>Xiplus-abot
0
已更改“[[Template:Small]]”的保护设置:高風險模板:101156引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<small>{{{1}}}</small><noinclude>
<!--Categories and interwikis go in the /doc sub-page.-->
{{Documentation|Template:Resize/doc}}
</noinclude>
ae7e668fc4870d13635bf6ddc8c1ae29f59df592
Template:Documentation
10
95
184
2024-01-27T09:22:43Z
zhwp>Ericliu1912
0
wikitext
text/x-wiki
{{#invoke:documentation|main|_content={{ {{#invoke:documentation|contentTitle}}}}}}
cc4eb5999a198597c14b859d18d2aa7b190e3af0
Documentation
0
289
601
2024-01-27T09:22:43Z
zhwp>Ericliu1912
0
wikitext
text/x-wiki
{{#invoke:documentation|main|_content={{ {{#invoke:documentation|contentTitle}}}}}}
cc4eb5999a198597c14b859d18d2aa7b190e3af0
Template:Demo
10
137
282
2024-02-23T09:45:06Z
zhwp>Sanmosa
0
Sanmosa移動頁面[[Template:Template Pre]]至[[Template:Demo]]:與enwiki一致
wikitext
text/x-wiki
{{#invoke:Demo|main}}<noinclude>{{documentation}}</noinclude>
e458e378477c6077a01987f334fdc73bee48512c
Template:Template Pre
10
138
284
2024-02-23T09:45:06Z
zhwp>Sanmosa
0
Sanmosa移動頁面[[Template:Template Pre]]至[[Template:Demo]]:與enwiki一致
wikitext
text/x-wiki
#REDIRECT [[Template:Demo]]
{{Redirect category shell|
{{移動重定向}}
}}
ca45b9d1eeba9e87cb533979d69ea5dcc0737bcf
Template:Namespace pagename
10
91
176
2024-03-01T13:08:25Z
zhwp>Shizhao
0
wikitext
text/x-wiki
{{{{{|safesubst:}}}If subst
| 1 = {{Namespace pagename{{{{{|safesubst:}}}#if:{{{1|}}}|{{{{{|safesubst:}}}!}}1{{{{{|safesubst:}}}=}}{{{1}}}}}{{{{{|safesubst:}}}#if:{{{2|}}}|{{{{{|safesubst:}}}!}}2{{{{{|safesubst:}}}=}}{{{2}}}}}}}
| 2 = <!--
-->{{#switch:<!--
---->{{#ifeq:{{{2|Empty}}}<!--
---->| Empty<!--
---->| {{ns:{{NAMESPACENUMBER}}}}<!-- If there is no input in {{{2}}}, then {{NAMESPACENUMBER}} will be returned.
---->| <!--
------>{{#if:{{#invoke:Page|isExternal|{{{2}}}}}<!--
------>| External<!--
------>| <!--
-------->{{#ifeq:{{{2}}}<!--
-------->| {{PAGENAME:{{{2}}}}}<!--
-------->| <!--
---------->{{#if:{{PAGENAME:{{ns:{{{2}}}}}}}<!--
---------->| {{ns:{{{2}}}}}<!--
---------->| <!--
------------>{{#switch:{{{2}}}<!--
------------>| MOS = MOS<!-- If {{{2}}} equals MOS, then MOS will be returned.
------------>| LTA = LTA<!-- If {{{2}}} equals LTA, then LTA will be returned.
------------>| NT = NT<!-- If {{{2}}} equals NT, then NT will be returned.
------------>| NC = NC<!-- If {{{2}}} equals NC, then NC will be returned.
------------>| #default = {{ns:0}}<!-- If there is no prefix in {{{2}}}, then {{ns:0}} will be returned.
------------>}}<!--
---------->}}<!--
-------->| {{NAMESPACE:{{{2}}}}}<!-- If {{{2}}} equals {{FULLPAGENAME}}, then {{NAMESPACE}} will be returned.
-------->}}<!--
------>}}<!--
---->}}<!--
-->| External = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 跨语言链接<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 跨語言連結<!--
---->| #default = Interlanguage link<!--
---->}}<!--
-->| MOS = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊捷徑<!--
---->| #default = Manual of Style<!--
---->}}<!--
-->| LTA = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者捷徑<!--
---->| #default = Long-term abuse<!--
---->}}<!--
-->| NT = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引捷徑<!--
---->| #default = Notability Guidelines<!--
---->}}<!--
-->| NC = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規捷徑<!--
---->| #default = Naming Conventions<!--
---->}}<!--
-->| {{ns:-2}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 媒体<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 媒體<!--
---->| #default = Media<!--
---->}}<!--
-->| {{ns:-1}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 特殊<!--
---->| #default = Special<!--
---->}}<!--
-->| {{ns:0}} = <!--
---->{{#switch:<!--
------>{{Str mid<!--
------>| {{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}<!--
------>| <!--
------>| {{#expr:abs({{str find|{{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}|:}})-1}}<!--
------>}}<!--
---->| MOS = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊捷徑<!--
------>| #default = Manual of Style<!--
------>}}<!--
---->| LTA = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者捷徑<!--
------>| #default = Long-term abuse<!--
------>}}<!--
---->| NT = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引捷徑<!--
------>| #default = Notability Guidelines<!--
------>}}<!--
---->| NC = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規捷徑<!--
------>| #default = Naming Conventions<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 条目<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 條目<!--
------>| #default = Article<!--
------>}}<!--
---->}}<!--
-->| {{ns:1}} = <!--
---->{{#switch:<!--
------>{{Str mid<!--
------>| {{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}<!--
------>| 6<!--
------>| {{#expr:abs({{Str find|{{str mid|{{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}|6}}|:}})-1}}<!--
------>}}<!--
---->| MOS = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊討論捷徑<!--
------>| #default = Manual of Style talk<!--
------>}}<!--
---->| LTA = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者討論捷徑<!--
------>| #default = Long-term abuse talk<!--
------>}}<!--
---->| NT = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引討論捷徑<!--
------>| #default = Notability Guidelines talk<!--
------>}}<!--
---->| NC = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規討論捷徑<!--
------>| #default = Naming Conventions talk<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 讨论<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 討論<!--
------>| #default = Talk<!--
------>}}<!--
---->}}<!--
-->| {{ns:2}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 用户<!--
---->| zh-hant | zh-hk | zh-mo = 用戶<!--
---->| zh-tw = 使用者<!--
---->| #default = User<!--
---->}}<!--
-->| {{ns:3}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 用户讨论<!--
---->| zh-hant | zh-hk | zh-mo = 用戶討論<!--
---->| zh-tw = 使用者討論<!--
---->| #default = User talk<!--
---->}}<!--
-->| {{ns:4}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 项目<!--
---->| zh-hant | zh-hk | zh-mo = 專案<!--
---->| zh-tw = 計畫<!--
---->| #default = Project<!--
---->}}<!--
-->| {{ns:5}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 项目讨论<!--
---->| zh-hant | zh-hk | zh-mo = 專案討論<!--
---->| zh-tw = 計畫討論<!--
---->| #default = Project talk<!--
---->}}<!--
-->| {{ns:6}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文件<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 檔案<!--
---->| #default = File<!--
---->}}<!--
-->| {{ns:7}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文件讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 檔案討論<!--
---->| #default = File talk<!--
---->}}<!--
-->| {{ns:8}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 界面<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 介面<!--
---->| #default = MediaWiki<!--
---->}}<!--
-->| {{ns:9}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 界面讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 介面討論<!--
---->| #default = MediaWiki talk<!--
---->}}<!--
-->| {{ns:10}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 模板<!--
---->| #default = Template<!--
---->}}<!--
-->| {{ns:11}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模板讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模板討論<!--
---->| #default = Template talk<!--
---->}}<!--
-->| {{ns:12}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 帮助<!--
---->| zh-hant | zh-hk | zh-mo = 幫助<!--
---->| zh-tw = 使用說明<!--
---->| #default = Help<!--
---->}}<!--
-->| {{ns:13}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 帮助讨论<!--
---->| zh-hant | zh-hk | zh-mo = 幫助討論<!--
---->| zh-tw = 使用說明討論<!--
---->| #default = Help talk<!--
---->}}<!--
-->| {{ns:14}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 分类<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 分類<!--
---->| #default = Category<!--
---->}}<!--
-->| {{ns:15}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 分类讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 分類討論<!--
---->| #default = Category talk<!--
---->}}<!--
-->| {{ns:100}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 主题<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 主題<!--
---->| #default = Portal<!--
---->}}<!--
-->| {{ns:101}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 主题讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 主題討論<!--
---->| #default = Portal talk<!--
---->}}<!--
-->| {{ns:102}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 维基专题<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 維基專題<!--
---->| #default = WikiProject<!--
---->}}<!--
-->| {{ns:103}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 维基专题讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 維基專題討論<!--
---->| #default = WikiProject talk<!--
---->}}<!--
-->| {{ns:118}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 草稿<!--
---->| #default = Draft<!--
---->}}<!--
-->| {{ns:119}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 草稿讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 草稿討論<!--
---->| #default = Draft talk<!--
---->}}<!--
-->| {{ns:710}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 字幕<!--
---->| #default = TimedText<!--
---->}}<!--
-->| {{ns:711}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 字幕讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 字幕討論<!--
---->| #default = TimedText talk<!--
---->}}<!--
-->| {{ns:828}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模块<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模組<!--
---->| #default = Module<!--
---->}}<!--
-->| {{ns:829}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模块讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模組討論<!--
---->| #default = Module talk<!--
---->}}<!--
-->| {{ns:2600}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 结构式讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 結構式討論<!--
---->| #default = Structured discussions<!--
---->}}<!--
-->| #default = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = {{Error|命名空间侦测错误。}}<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = {{Error|命名空間偵測錯誤。}}<!--
---->| #default = {{Error|There's an error in the detection of namespace.}}<!--
---->}}<!--
-->}}<!--
-->{{#switch:{{#invoke:Page|contentModel|{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{{2}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}}}<!--
-->| css | sanitized-css = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 样式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 樣式<!--
---->| #default = styles<!--
---->}}<!--
-->| javascript = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 脚本<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 工具<!--
---->| #default = scripts<!--
---->}}<!--
-->| json = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 数据<!--
---->| zh-hant | zh-hk | zh-mo = 數據<!--
---->| zh-tw = 資料<!--
---->| #default = data<!--
---->}}<!--
-->| #default = <!--
---->{{#switch:<!--
------>{{#if:{{{2|}}}<!--
------>| <!--
-------->{{#ifeq:{{{2}}}<!--
-------->| {{PAGENAME:{{{2}}}}}<!--
-------->| <!--
-------->| <!--
---------->{{#if:{{#ifeq:{{{}}}|R|{{#invoke:Page|isRedirect|{{{2}}}}}}}<!--
---------->| Redirect<!--
---------->| <!--
------------>{{If in page<!--
------------>| page = {{{2}}}<!--
------------>| %{%{[Dd]ocumentation[_%s]subpage<!--
------------>| doc<!--
------------>| <!--
-------------->{{If in page<!--
-------------->| page = {{{2}}}<!--
-------------->| %{%{[Tt]emplate[_%s]doc[_%s]page[_%s]viewed[_%s]directly<!--
-------------->| doc<!--
-------------->| <!--
---------------->{{If in page<!--
---------------->| page = {{{2}}}<!--
---------------->| %{%{[Ss]andbox<!--
---------------->| sandbox<!--
---------------->| <!--
------------------>{{If in page<!--
------------------>| page = {{{2}}}<!--
------------------>| %{%{[Ss]andbox[_%s]heading<!--
------------------>| sandbox<!--
------------------>| <!--
-------------------->{{If in page<!--
-------------------->| page = {{{2}}}<!--
-------------------->| %{%{请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。<!--
-------------------->| sandbox<!--
-------------------->| <!--
---------------------->{{If in page<!--
---------------------->| page = {{{2}}}<!--
---------------------->| %{%{請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。<!--
---------------------->| sandbox<!--
---------------------->| <!--
------------------------>{{If in page<!--
------------------------>| page = {{{2}}}<!--
------------------------>| %{%{[Tt]emplate[_%s]sandbox[_%s]notice<!--
------------------------>| sandbox<!--
------------------------>| <!--
-------------------------->{{If in page<!--
-------------------------->| page = {{{2}}}<!--
-------------------------->| %{%{[Tt]estcases[_%s]notice<!--
-------------------------->| testcases<!--
-------------------------->| <!--
---------------------------->{{If in page<!--
---------------------------->| page = {{{2}}}<!--
---------------------------->| %{%{[Tt]emplate[_%s]test[_%s]cases[_%s]notice<!--
---------------------------->| testcases|<!--
------------------------------>{{If in page<!--
------------------------------>| page = {{{2}}}<!--
------------------------------>| %{%{测试样例<!--
------------------------------>| testcases<!--
------------------------------>| <!--
-------------------------------->{{If in page<!--
-------------------------------->| page = {{{2}}}<!--
-------------------------------->| %{%{測試樣例<!--
-------------------------------->| testcases<!--
-------------------------------->| {{SUBPAGENAME:{{Str right|{{{2}}}|5}}}}<!--
-------------------------------->}}<!--
------------------------------>}}<!--
---------------------------->}}<!--
-------------------------->}}<!--
------------------------>}}<!--
---------------------->}}<!--
-------------------->}}<!--
------------------>}}<!--
---------------->}}<!--
-------------->}}<!--
------------>}}<!--
---------->}}<!--
-------->}}<!--
------>| {{SUBPAGENAME}}<!--
------>}}<!--
---->| Redirect = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 重定向<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 重新導向<!--
------>| #default = redirect<!--
------>}}<!--
---->| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文档<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 文件<!--
-------->| #default = documentation<!--
-------->}}<!--
------>}}<!--
---->| sandbox | Sandbox | 沙盒 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 沙盒<!--
-------->| #default = sandbox<!--
-------->}}<!--
------>}}<!--
---->| testcases | Testcases | 测试样例 | 測試樣例 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 测试样例<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 測試樣例<!--
-------->| #default = testcases<!--
-------->}}<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:1}} | {{ns:3}} | {{ns:4}} | {{ns:5}} | {{ns:7}} | {{ns:8}} | {{ns:9}} | {{ns:11}} | {{ns:12}} | {{ns:13}} | {{ns:15}} | {{ns:101}} | {{ns:103}} | {{ns:119}} | {{ns:829}} | {{ns:2301}} | {{ns:2302}} | {{ns:2303}} | {{ns:2600}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 頁<!--
-------->| #default = page<!--
-------->}}<!--
------>| {{ns:-2}} | {{ns:-1}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页面<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 頁面<!--
-------->| #default = page<!--
-------->}}<!--
------>| {{ns:2}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页<!--
-------->| zh-hant | zh-hk | zh-mo = 頁<!--
-------->| zh-tw = 頁面<!--
-------->| #default = page<!--
-------->}}<!--
------>}}<!--
---->}}<!--
-->}}
}}<noinclude>
{{Documentation}}</noinclude>
18c73d7accdd7e8b2f9f30db4a9721a43dbdd799
Template:TemplateData header
10
107
208
2024-03-09T15:18:02Z
zhwp>PexEric
0
wikitext
text/x-wiki
<div class="templatedata-header">{{#if:{{{noheader|}}}| |以下是该模板的{{#if:{{{nolink|}}}|-{zh-cn:模板数据;zh-tw:模板資料}-|[[那艺娜维基:模板数据|-{zh-cn:模板数据;zh-tw:模板資料}-]]}},适用于[[那艺娜维基:可视化编辑器|-{zh-cn:可视化编辑器;zh-tw:視覺化編輯器;}-]]等工具。}}
'''{{{1|{{BASEPAGENAME}}}}}-{zh-cn:模板数据;zh-tw:模板資料}-'''
</div><includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:模板数据文档]]
}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
d02fc282d251516ba7c50d0ba1fbca94c816036d
392
208
2024-03-09T15:18:02Z
zhwp>PexEric
0
wikitext
text/x-wiki
<div class="templatedata-header">{{#if:{{{noheader|}}}| |以下是该模板的{{#if:{{{nolink|}}}|-{zh-cn:模板数据;zh-tw:模板資料}-|[[Wikipedia:模板数据|-{zh-cn:模板数据;zh-tw:模板資料}-]]}},适用于[[Wikipedia:可视化编辑器|-{zh-cn:可视化编辑器;zh-tw:視覺化編輯器;}-]]等工具。}}
'''{{{1|{{BASEPAGENAME}}}}}-{zh-cn:模板数据;zh-tw:模板資料}-'''
</div><includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:模板数据文档]]
}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
982e2539923433acdd960513bacedcb39c3280c5
Template:Esoteric
10
197
412
2024-03-14T03:31:51Z
zhwp>蕭漫
0
+{{[[Template:Pp-template|Pp-template]]}}
wikitext
text/x-wiki
#重定向 [[Template:Intricate template]]
{{Pp-template|small=yes}}
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
}}
763c8d2bf303bd0cf855c67f6c423acce73c2ac8
Template:Link-ja
10
315
655
2024-03-14T03:32:14Z
zhwp>蕭漫
0
+{{[[Template:Pp-template|Pp-template]]}}
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/ja]]
{{Pp-template|small=yes}}
{{Redirect category shell|1=
{{模板重定向}}
{{模板捷徑重定向}}
}}
02b0318a941508fba7a779c4f34ac6e9a358525c
Template:Reflist/doc
10
209
436
2024-03-15T11:31:13Z
zhwp>HoweyYuan
0
// Edit via Wikiplus
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{Documentation subpage}}
{{High-use|all-pages=yes}}
{{Esoteric}}
<!-- 在本行下編輯模板說明 -->
使用本模板可在條目中顯示註腳({{tag|ref}})列表。其涵盖了{{tag|references|s}}的所有功能。
==参数解说 ==
{{tlc|1=Reflist|2=欄位數/欄位寬度|3=group=组别|4=refs=列表內容|5=liststyle=|6=list=}}
本模板所有参数均为可选
; 无名参数1
: 按固定寬度分欄(填入[[em (字体排印学)|em]]等排印单位):如{{tlc|Reflist|25em}},瀏覽器會依照這個數值和當前的視窗大小,自動調整欄位數目。
: 按列数分欄(填入自然数;此機制不建議使用):如{{tlc|Reflist|2}}將會創造出一個兩欄式的的注釋列表,而{{tlc|Reflist|3}}會產生一個三欄式的列表。視窗大小可变,请慎重定义列数。
: 不填任何内容默认为1。
; <code>group</code>
: 参见[[#分組註釋|分组注释]]
; <code>refs</code>
: 将脚注内容集中到一起存放,参见[[#统一存放参考信息集]]
; <code>liststyle</code>
:
; <code>list</code>
: 手工列出一般参考资料,使用此参数时,模板原本列出{{tag|references|s}}的功能会无效化。可用{{tl|ReflistH}}/{{tl|ReflistF}}模板替代。
=== 过时参数 ===
; <code>colwidth</code>
: 已合并到无名参数1
== 用法 ==
{{markup|title=只使用内文注释
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist}}
}}
{{markup|title=只使用一般注释
|<nowiki>一條青龍一氣通,二盤連莊二本場。
==參考資料==
{{Reflist|list=
* 书目a
* 书目b
}}</nowiki>
|一條青龍一氣通,二盤連莊二本場。
{{fake heading|參考資料}}
{{Reflist|list=
* 书目a
* 书目b
}}
}}
{{markup|title=内文与一般注释混合使用
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist}}
{{Reflist|list=
* 书目a
* 书目b
}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist}}
{{Reflist|list=
* 书目a
* 书目b
}}
}}
=== 分栏 ===
{{Rellink|不支持Internet Explorer 9、Firefox 1.0、Safari 2、Opera 11.0及更低版本,这些浏览器只会显示为单行}}
複數欄位是使用 [[CSS|CSS3]] 作為基礎,目前使用[[Gecko]](如[[Mozilla Firefox]]等)与[[Kestrel]]([[Opera (瀏覽器)]]9.5及以上版本)作排版引擎的瀏覽器會得到較佳的效果{{efn-ur|1={{cite web|url=http://www.stuffandnonsense.co.uk/archives/css3_multi-column_thriller.html|title=CSS3 Multi-Column Thriller|accessdate=2006年11月24日|date=2005年12月30日}}}},但由於 CSS 是網頁上的標準之一,因此日後將能適用在更多的瀏覽器{{efn-ur|1={{cite web|url=http://www.w3.org/TR/css3-multicol|title=CSS3 module: Multi-column layout|publisher=[[World Wide Web Consortium|W3C]]|date=2005年12月15日|accessdate=2006年11月24日}}}}。
按宽度分栏(例如<code><nowiki>{{Reflist|30em}}</nowiki></code>)会让浏览器在给定最小宽度的前提下(如宽度至少为30 em),显示尽可能多的栏目。宽度单位支持em, ex, in, cm, mm, pt, pc, px,但是通常使用em。数字和单位之间不能有空格。不支持使用百分比。
根据参考内容的宽度选择合适的宽度:
* 30em:当有大量参考文献且参考条目有一页宽时适用。例如:{{oldid|張伯苓|71040939#参考文献}}
* 20em:当有宽度较短的[[哈佛参考文献格式]](如{{t1|Template:Sfn}})时适用。例如:{{oldid|南方十字 (无字小说)|71611463#脚注}}.
{{markup|title=分为2栏
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist|2}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist|2}}
}}
{{markup|title=按30em宽度分栏
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist|30em}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist|30em}}
}}
=== 分組註釋 ===
於2008年6月開始,腳註系統支援了把註釋分成不同組合。這允許組合註釋、參考以及其他。請參閱 {{en icon}}[[:en:Wikipedia:Footnotes#Separating reference lists and explanatory notes|Wikipedia:Footnotes#Separating reference lists and explanatory notes]]。
標籤的原始碼为{{tag|ref group=''"groupname"''|open}},对应註腳列表的原始碼,{{tlx|Reflist|group=''"groupname"''}}。而其中的「groupname」是組合的名稱,如「注」、「参」或「标签」。注意groupname对简繁体敏感。
部分分组会显示特殊效果,如{{tag|ref|params=group="upper-alpha"}}的生成的脚注为{{dummy ref|A}},{{tag|ref|params=group="lower-alpha"}}生成的为{{dummy ref|a}}。
{{markup | title = 按“注释”和“参考”分组
|<nowiki>三元兼四喜,滿貫<ref group="注释">注释1</ref>遇全么<ref group="参考">参考1</ref>。
花<ref group="注释">注释2</ref>自槓頭髮,月從海底撈<ref group="参考">参考2</ref>。
==注释和参考资料==
===注释===
{{Reflist|group=注释}}
===参考===
{{Reflist|group=参考}}</nowiki>
|三元兼四喜,滿貫<ref group="注释">注释1</ref>遇全么<ref group="参考">参考1</ref>。
花<ref group="注释">注释2</ref>自槓頭髮,月從海底撈<ref group="参考">参考2</ref>。
{{fake heading|注释和参考资料}}
{{fake heading|sub=3|注释}}
{{Reflist|group=注释}}
{{fake heading|sub=3|参考}}
{{Reflist|group=参考}}
}}
=== 统一存放参考信息集 ===
<!-- As of September 2009, references may be defined within {{tl|Reflist}} using {{para|refs}} and invoked within the content. There are new error messages associated with this update, documented at [[Help:Cite errors]]. -->
从2014年2月开始,该模板可以通过{{para|refs}}统一存放注脚信息来方便管理。此次更新的相關引用错误问题的提示文件見[[:en:Help:Cite errors]]。
{{markup | title = 示例
|<nowiki>这是参考A<ref name="refname1" />。
这是参考B<ref name="refname2" />。
==参考资料==
{{Reflist|refs=
<ref name="refname1">内容1</ref>
<ref name="refname2">内容2</ref>
}}</nowiki>
|这是参考A<ref name="refname1" group=upper-alpha/>。
这是参考B<ref name="refname2" group=upper-alpha/>。
{{fake heading|参考资料}}
{{Reflist|group=upper-alpha|refs=
<ref name="refname1">内容1</ref>
<ref name="refname2">内容2</ref>
}}
}}
==模板數據==
{{templatedataheader}}
<templatedata>
{
"description": "在條目中加入一個使用較小字級顯示的註腳列表。",
"params": {
"colwidth": {
"label": "欄位的寬度",
"description": "瀏覽器會依照這個數值和當前的視窗大小自動調整欄位數目,請依照該頁面中注釋的平均寬度來填寫欄位的寬度數值。填入後參數「1」將被忽略。",
"type": "string/line",
"required": false
},
"1": {
"label": "欄位的數目",
"description": "欄位的數目,填入2將創造一個兩欄式的的注釋列表,如此類推。",
"type": "number",
"default": "1",
"required": false
},
"list": {
"label": "自定義註釋內容",
"description": "自定義註釋內容。",
"default": "<references />",
"type": "string",
"required": false
},
"refs": {
"type": "string",
"required": false
},
"group": {
"label": "註腳組別名稱",
"description": "註腳組別的名稱,即在插入參考文獻時「使用此組」輸入的名稱。",
"type": "string/line",
"required": false
}
}
}
</templatedata>
==参考文献==
{{notelist-ur}}
==參見==
* {{tlx|ReferencesWithExtra}}
* {{tlx|Notelist}}
* {{tlx|Template reference list}}
* 在討論頁顯示參考文獻請用{{tlx|Reflist-talk}}
* [[Help:脚注]]
* [[Wikipedia:列明来源]]
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[Wikipedia:Wikidata]]) -->
[[Category:引用模板| ]]
[[Category:頁面訊息模板|註]]
}}</includeonly>
== 重定向 ==
* {{模板鏈接|註腳}}
ae69ecb71e6788aa15a356de1ed3c91e6f058be2
Module:About
828
103
200
2024-03-29T10:36:56Z
zhwp>Dabao qian
0
Scribunto
text/plain
local mArguments --initialize lazily
local ifmobile = require('Module:If mobile')
local mHatnote = require('Module:Hatnote')
local mHatList = require('Module:Hatnote list')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
function p.about (frame)
-- A passthrough that gets args from the frame and all
mArguments = require('Module:Arguments')
args = mArguments.getArgs(frame)
return p._about(args)
end
function p._about (args, options)
-- Produces "about" hatnote.
-- Type checks and defaults
checkType('_about', 1, args, 'table', true)
args = args or {}
checkType('_about', 2, options, 'table', true)
options = options or {}
local defaultOptions = {
aboutForm = '此%s介紹的是%s。',
PageType = require('Module:Pagetype').main(),
namespace = mw.title.getCurrentTitle().namespace,
otherText = nil, --included for complete list
sectionString = '章节'
}
for k, v in pairs(defaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Set initial "about" string
local pageType = (args.section and options.sectionString) or options.PageType
local about = ''
if args[1] then
about = string.format(options.aboutForm, pageType, args[1])
end
--Allow passing through certain options
local fsOptions = {
otherText = options.otherText,
extratext = args.text
}
local hnOptions = {
selfref = args.selfref
}
-- Set for-see list
local forSee = mHatList._forSee(args, 2, fsOptions)
local image = '[[File:Disambig_gray.svg|25px|link=那艺娜维基:消歧义|alt=]]'
local mobview = ifmobile._main({nil, ' '})
-- Concatenate and return
return mHatnote._hatnote(image .. mobview .. about .. forSee, hnOptions)
end
return p
a1e813f1f5c49f3f63e65f0d5a8e6c47473f738e
那艺娜维基:If mobile
4
12
19
2024-03-29T16:57:24Z
zhwp>Dabao qian
0
wikitext
text/x-wiki
{{#invoke:If mobile|main}}<noinclude>
{{Documentation}}</noinclude>
704e8b891b9980b01d12ed061de7486c87b2274b
Template:If mobile
10
36
67
2024-03-29T16:57:24Z
zhwp>Dabao qian
0
wikitext
text/x-wiki
{{#invoke:If mobile|main}}<noinclude>
{{Documentation}}</noinclude>
704e8b891b9980b01d12ed061de7486c87b2274b
Module:If mobile
828
56
105
2024-03-29T20:50:54Z
zhwp>Xiplus-abot
0
已保护“[[Module:If mobile]]”:高風險模板:70504引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
local p = {}
function p._main(args)
local frame = mw.getCurrentFrame()
local root = mw.html.create()
if args["Tag"] then
args["tag"] = args["Tag"]
end
local ifmobile = root:tag(args["tag"] or 'span')
ifmobile
:addClass('ifmobile')
local nomobile = ifmobile:tag(args["tag"] or 'span')
local mobile = ifmobile:tag(args["tag"] or 'span')
nomobile
:addClass('nomobile')
:wikitext(args[2])
mobile
:addClass('mobile')
:wikitext(args[1])
return frame:extensionTag {name = 'templatestyles', args = {src = 'If mobile/styles.css'}} .. tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:If mobile'
})
return p._main(args)
end
return p
0dc3a7be7f6c018c054779b0c4b4cc1f43380752
Template:Film and Television related infobox templates
10
223
464
2024-04-03T18:02:07Z
zhwp>Dabao qian
0
wikitext
text/x-wiki
{{Navbox
| name = Film and Television related infobox templates
| title = 广播、电影、电视、戏剧行业相关信息框模板
| tracking = <includeonly>no</includeonly>
| bodyclass = hlist
| state = {{{state|autocollapse}}}
| above =
* [[Wikipedia:格式手册/信息框|格式手册(-{zh-hans:信息;zh-hant:資訊;}-框)]]
* [[WikiProject:维基百科/信息框工作组|维基百科专题信息框工作组]]
| group1 = 广播业
| list1 =
* [[T:廣播电台|广播电台]]
* [[T:電台節目信息框|电台节目]]
| group2 = 电影业
| list2 =
* [[T:电影信息框|电影]]
** [[T:Based on|原著]]
** [[:Category:电影产地模板|产地]]
** [[T:CFA|公映许可]]
* [[T:Infobox cinema market|电影市场]]
* [[T:Infobox film festival|电影节]]
| group3 = 电视业
| list3 = {{navbox|child|
|group1 = 平台
|list1 =
* [[T:電視網資訊|电视网]]
* [[T:电视频道信息框|电视频道]]
|group2 = 内容
|list2 =
* [[T:电视节目信息框|电视节目]]
* [[T:Infobox television season|系列節目-簡短]]
* [[T:系列节目信息框|系列节目-詳細]]
** [[T:Infobox reality competition season|真人秀比赛播出季]]
** [[T:极速前进信息框|极速前进]]
** [[T:Infobox reality music competition|真人秀音乐比赛]]
* [[T:Infobox television episode|电视剧分集]]
** [[T:Infobox Doctor Who episode|-{zh-cn:神秘博士;zh-hk:異世奇人;zh-tw:超時空奇俠;}-]]
** [[T:Infobox Futurama episode|-{zh-cn:飞出个未来;zh-hk:乃出個未來;zh-tw:飛出個未來;}-]]
** [[T:Infobox Simpsons episode|-{zh-cn:辛普森一家;zh-hk:阿森一族;zh-tw:辛普森家庭;}-]]
* [[T:Infobox machinima|引擎电影]]
* [[T:Infobox animanga/TVAnime|电视动画]]
** [[T:Infobox animanga/OVA|OVA]]
* [[T:Infobox beauty pageant|選美比賽]]
}}
| group4 = 戏剧业
| list4 =
* [[T:Infobox play|剧目]]
* [[T:马戏团信息框|马戏团]]
| group5 = 衍生产业
| list5 =
* [[T:Infobox advertising|广告]]
* [[T:Infobox podcast|播客]]
| group6 = 技术
| list6 =
* [[T:Infobox camera|相机]]
* [[T:Infobox photographic lens|镜头]]
* [[T:Infobox photographic film|胶片]]
* [[T:Infobox font|电脑字体]]
| group7 = 人物
| list7 =
* [[T:藝人|艺人]]
** [[T:AV女优|AV女优]]
** [[T:Infobox AKB48 member|AKB48集团成员]]
** [[T:Infobox Sakamichi-series member|坂道系成员]]
** [[T:Infobox SNH48 member|SNH48 Group成员]]
* [[T:Infobox YouTube personality|YouTube用户]]
* [[T:Infobox bilibili personality|哔哩哔哩用户]]
* [[T:Infobox Xigua Video personality|西瓜视-{}-频用户]]
* [[T:Infobox Douyin personality|抖音用户]]
* [[T:Infobox online streamer|网络主播]]
* [[T:Infobox vtuber|VTuber]]
| group8 = 虚构元素
| list8 =
* [[T:Infobox fictional artifact|物品]]
* [[T:Infobox character|角色]]
** [[T:Doctor Who doctor|《-{zh-cn:神秘博士;zh-hk:異世奇人;zh-tw:超時空奇俠;}-》博士]]
** [[T:火影忍者人物|火影忍者]]
** [[T:Simpsons character|-{zh-cn:辛普森一家;zh-hk:阿森一族;zh-tw:辛普森家庭;}-]]
** [[Template:原神角色|原神]]
** [[Template:崩坏:星穹铁道角色|崩坏:星穹铁道]]
** [[Template:紅樓夢人物|紅樓夢]]
* [[T:Infobox fictional location|地点]]
* [[T:Infobox fictional organisation|组织]]
* [[T:Infobox fictional race|种族]]
* [[T:虚构飞船信息框|飞船]]
| group9 = 其他
| list9 =
* [[T:Infobox media franchise|跨媒体制作]]
* [[T:Infobox award|颁奖礼]]
* [[T:Infobox awards list|奖项列表]]
* [[T:Infobox film awards|电影奖项]]
** [[T:Infobox film awards/link|-{zh-hans:链接;zh-hant:連結;}-]]
** [[T:Infobox film awards/style|格式]]
* [[T:Listen|试听]]
}}<noinclude>
{{Navbox documentation}}
[[Category:模板說明文件導航模板]]
</noinclude>
993b11816493102e877a495ec375386966e44c02
Module:Age
828
227
473
2024-04-04T08:07:46Z
zhwp>Ericliu1912
0
依據編輯請求更新頁面
Scribunto
text/plain
-- Implement various "age of" and other date-related templates.
local _Date, _currentDate
local function getExports(frame)
-- Return objects exported from the date module or its sandbox.
if not _Date then
local sandbox = frame:getTitle():find('sandbox', 1, true) and '/sandbox' or ''
local datemod = require('Module:Date' .. sandbox)
_Date = datemod._Date
_currentDate = datemod._current
end
return _Date, _currentDate
end
local Collection -- a table to hold items
Collection = {
add = function (self, item)
if item ~= nil then
self.n = self.n + 1
self[self.n] = item
end
end,
join = function (self, sep)
return table.concat(self, sep)
end,
remove = function (self, pos)
if self.n > 0 and (pos == nil or (0 < pos and pos <= self.n)) then
self.n = self.n - 1
return table.remove(self, pos)
end
end,
sort = function (self, comp)
table.sort(self, comp)
end,
new = function ()
return setmetatable({n = 0}, Collection)
end
}
Collection.__index = Collection
local function stripToNil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (which may, for example, be nil).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local yes = require('Module:Yesno')
local function message(msg, id)
-- Return formatted message text for an error or warning.
local categories = {
error = '[[Category:Age模块错误]]',
warning = '[[Category:Age模块错误]]', -- same as error until determine whether 'Age warning' would be worthwhile
}
local a, b, category
if id == 'warning' then
a = '<sup>[<i>'
b = '</i>]</sup>'
else
a = '<strong class="error">错误:'
b = '</strong>'
end
if mw.title.getCurrentTitle():inNamespaces(0) then
-- Category only in namespaces: 0=article.
category = categories[id or 'error']
end
return
a ..
mw.text.nowiki(msg) ..
b ..
(category or '')
end
local function formatNumber(number)
-- Return the given number formatted with commas as group separators,
-- given that the number is an integer.
local numstr = tostring(number)
local length = #numstr
local places = Collection.new()
local pos = 0
repeat
places:add(pos)
pos = pos + 3
until pos >= length
places:add(length)
local groups = Collection.new()
for i = places.n, 2, -1 do
local p1 = length - places[i] + 1
local p2 = length - places[i - 1]
groups:add(numstr:sub(p1, p2))
end
return groups:join(',')
end
local function spellNumber(number, options, i)
-- Return result of spelling number, or
-- return number (as a string) if cannot spell it.
-- i == 1 for the first number which can optionally start with an uppercase letter.
number = tostring(number)
return require('Module:ConvertNumeric').spell_number(
number,
nil, -- fraction numerator
nil, -- fraction denominator
i == 1 and options.upper, -- true: 'One' instead of 'one'
not options.us, -- true: use 'and' between tens/ones etc
options.adj, -- true: hyphenated
options.ordinal -- true: 'first' instead of 'one'
) or number
end
local function makeSort(value, sortable)
-- Return a sort key if requested.
-- Assume value is a valid number which has not overflowed.
if sortable == 'sortable_table' or sortable == 'sortable_on' or sortable == 'sortable_debug' then
local sortkey
if value == 0 then
sortkey = '5000000000000000000'
else
local mag = math.floor(math.log10(math.abs(value)) + 1e-14)
local prefix
if value > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
value = value + 10^(mag+1)
end
sortkey = string.format('%d', prefix) .. string.format('%015.0f', math.floor(value * 10^(14-mag)))
end
local lhs, rhs
if sortable == 'sortable_table' then
lhs = 'data-sort-value="'
rhs = '"|'
else
lhs = sortable == 'sortable_debug' and
'<span style="border:1px solid;display:inline;" class="sortkey">' or
'<span style="display:none" class="sortkey">'
rhs = '♠</span>'
end
return lhs .. sortkey .. rhs
end
end
local translateParameters = {
abbr = {
off = 'abbr_off',
on = 'abbr_on',
},
disp = {
age = 'disp_age',
raw = 'disp_raw',
},
format = {
raw = 'format_raw',
commas = 'format_commas',
},
round = {
on = 'on',
yes = 'on',
months = 'ym',
weeks = 'ymw',
days = 'ymd',
hours = 'ymdh',
},
sep = {
comma = 'sep_comma',
[','] = 'sep_comma',
serialcomma = 'sep_serialcomma',
space = 'sep_space',
},
show = {
hide = { id = 'hide' },
y = { 'y', id = 'y' },
ym = { 'y', 'm', id = 'ym' },
ymd = { 'y', 'm', 'd', id = 'ymd' },
ymw = { 'y', 'm', 'w', id = 'ymw' },
ymwd = { 'y', 'm', 'w', 'd', id = 'ymwd' },
yd = { 'y', 'd', id = 'yd', keepZero = true },
m = { 'm', id = 'm' },
md = { 'm', 'd', id = 'md' },
w = { 'w', id = 'w' },
wd = { 'w', 'd', id = 'wd' },
h = { 'H', id = 'h' },
hm = { 'H', 'M', id = 'hm' },
hms = { 'H', 'M', 'S', id = 'hms' },
d = { 'd', id = 'd' },
dh = { 'd', 'H', id = 'dh' },
dhm = { 'd', 'H', 'M', id = 'dhm' },
dhms = { 'd', 'H', 'M', 'S', id = 'dhms' },
ymdh = { 'y', 'm', 'd', 'H', id = 'ymdh' },
ymdhm = { 'y', 'm', 'd', 'H', 'M', id = 'ymdhm' },
ymwdh = { 'y', 'm', 'w', 'd', 'H', id = 'ymwdh' },
ymwdhm = { 'y', 'm', 'w', 'd', 'H', 'M', id = 'ymwdhm' },
},
sortable = {
off = false,
on = 'sortable_on',
table = 'sortable_table',
debug = 'sortable_debug',
},
}
local spellOptions = {
cardinal = {},
Cardinal = { upper = true },
cardinal_us = { us = true },
Cardinal_us = { us = true, upper = true },
ordinal = { ordinal = true },
Ordinal = { ordinal = true, upper = true },
ordinal_us = { ordinal = true, us = true },
Ordinal_us = { ordinal = true, us = true, upper = true },
}
local function dateExtract(frame)
-- Return part of a date after performing an optional operation.
local Date = getExports(frame)
local args = frame:getParent().args
local parms = {}
for i, v in ipairs(args) do
parms[i] = v
end
if yes(args.fix) then
table.insert(parms, 'fix')
end
if yes(args.partial) then
table.insert(parms, 'partial')
end
local show = stripToNil(args.show) or 'dmy'
local date = Date(unpack(parms))
if not date then
if show == 'format' then
return 'error'
end
return message('需要有效的日期')
end
local add = stripToNil(args.add)
if add then
for item in add:gmatch('%S+') do
date = date + item
if not date then
return message('无法添加“' .. item .. '”')
end
end
end
local prefix, result
local sortable = translateParameters.sortable[args.sortable]
if sortable then
local value = (date.partial and date.partial.first or date).jdz
prefix = makeSort(value, sortable)
end
if show ~= 'hide' then
result = date[show]
if result == nil then
result = date:text(show)
elseif type(result) == 'boolean' then
result = result and '1' or '0'
else
result = tostring(result)
end
end
return (prefix or '') .. (result or '')
end
local function rangeJoin(range)
-- Return text to be used between a range of ages.
return range == 'dash' and '—' or '或'
end
local function makeText(values, components, names, options, noUpper)
-- Return wikitext representing an age or duration.
local text = Collection.new()
local count = #values
local sep = names.sep or ''
for i, v in ipairs(values) do
-- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years).
local islist = type(v) == 'table'
if (islist or v > 0) or (text.n == 0 and i == count) or (text.n > 0 and components.keepZero) then
local fmt, vstr
if options.spell then
fmt = function(number)
return spellNumber(number, options.spell, noUpper or i)
end
elseif i == 1 and options.format == 'format_commas' then
-- Numbers after the first should be small and not need formatting.
fmt = formatNumber
else
fmt = tostring
end
if islist then
vstr = fmt(v[1]) .. rangeJoin(options.range)
noUpper = true
vstr = vstr .. fmt(v[2])
else
vstr = fmt(v)
end
local name = names[components[i]]
if name then
local plural = names.plural
if not plural or (islist and v[2] or v) == 1 then
plural = ''
end
text:add(vstr .. sep .. name .. plural)
else
text:add(vstr)
end
end
end
local first, last
-- hh mm ss
if options.join == 'sep_space' then
first = ' '
last = ' '
-- hh时,mm分,ss秒
elseif options.join == 'sep_comma' then
first = ','
last = ','
-- hh时,mm分又ss秒
elseif options.join == 'sep_serialcomma' then
first = ','
last = text.n > 2 and (names.y == '年' and '又' or '零') or ','
-- hh时mm分ss秒
elseif options.join == 'sep_none' then
first = ''
last = ''
-- hh时mm分又ss秒
else -- 'sep_serial'
first = ''
last = text.n > 2 and (names.y == '年' and '又' or '零') or ''
end
for i, v in ipairs(text) do
if i < text.n then
text[i] = v .. (i + 1 < text.n and first or last)
end
end
local sign = ''
if options.isnegative then
-- Do not display negative zero.
if text.n > 1 or (text.n == 1 and text[1]:sub(1, 1) ~= '0' ) then
if options.format == 'format_raw' then
sign = '-' -- plain hyphen so result can be used in a calculation
else
sign = '−' -- Unicode U+2212 MINUS SIGN
end
end
end
return
(options.prefix or '') ..
(options.extra or '') ..
sign ..
text:join() ..
(options.suffix or '')
end
local function dateDifference(parms)
-- Return a formatted date difference using the given parameters
-- which have been validated.
local names = {
abbr_off = {
plural = '',
sep = '',
y = '年',
m = '个月',
w = '周',
d = '天',
H = '小时',
M = '分',
S = '秒',
},
abbr_on = {
y = 'y',
m = 'm',
w = 'w',
d = 'd',
H = 'h',
M = 'm',
S = 's',
},
abbr_age = {
plural = '',
sep = '',
y = '岁',
m = '个月',
w = '周',
d = '天',
H = '小时',
M = '分',
S = '秒',
},
abbr_raw = {},
}
local diff = parms.diff -- must be a valid date difference
local show = parms.show -- may be nil; default is set below
local abbr = parms.abbr or 'abbr_off'
local defaultJoin -- 中文应该全为nil
if abbr ~= 'abbr_off' then
defaultJoin = nil
end
if not show then
show = 'ymd'
if parms.disp == 'disp_age' then
if diff.years < 3 then
defaultJoin = nil
if diff.years >= 1 then
show = 'ym'
else
show = 'md'
end
else
show = 'y'
end
end
end
if type(show) ~= 'table' then
show = translateParameters.show[show]
end
if parms.disp == 'disp_raw' then
defaultJoin = 'sep_space'
abbr = 'abbr_raw'
elseif parms.wantSc then
defaultJoin = 'sep_serialcomma'
end
local diffOptions = {
round = parms.round,
duration = parms.wantDuration,
range = parms.range and true or nil,
}
local prefix
if parms.sortable then
local value = diff.age_days + (parms.wantDuration and 1 or 0) -- days and fraction of a day
if diff.isnegative then
value = -value
end
prefix = makeSort(value, parms.sortable)
end
local textOptions = {
prefix = prefix,
suffix = parms.suffix, -- not currently used
extra = parms.extra,
format = parms.format,
join = parms.sep or defaultJoin,
isnegative = diff.isnegative,
range = parms.range,
spell = parms.spell,
}
if show.id == 'hide' then
return prefix or ''
end
local values = { diff:age(show.id, diffOptions) }
if values[1] then
return makeText(values, show, names[abbr], textOptions)
end
if diff.partial then
-- Handle a more complex range such as
-- {{age_yd|20 Dec 2001|2003|range=yes}} → 1 year, 12 days or 2 years, 11 days
local opt = {
format = textOptions.format,
join = textOptions.join,
isnegative = textOptions.isnegative,
spell = textOptions.spell,
}
return
(textOptions.prefix or '') ..
makeText({ diff.partial.mindiff:age(show.id, diffOptions) }, show, names[abbr], opt) ..
rangeJoin(textOptions.range) ..
makeText({ diff.partial.maxdiff:age(show.id, diffOptions) }, show, names[abbr], opt, true) ..
(textOptions.suffix or '')
end
return message('此处不支持参数show=' .. show.id)
end
local function getDates(frame, getopt)
-- Parse template parameters and return one of:
-- * date (a date table, if single)
-- * date1, date2 (two date tables, if not single)
-- * text (a string error message)
-- A missing date is optionally replaced with the current date.
-- If wantMixture is true, a missing date component is replaced
-- from the current date, so can get a bizarre mixture of
-- specified/current y/m/d as has been done by some "age" templates.
-- Some results may be placed in table getopt.
local Date, currentDate = getExports(frame)
getopt = getopt or {}
local function flagCurrent(text)
-- This allows the calling template to detect if the current date has been used,
-- that is, whether both dates have been entered in a template expecting two.
-- For example, an infobox may want the age when an event occurred, not the current age.
-- Don't bother detecting if wantMixture is used because not needed and it is a poor option.
if not text then
text = 'currentdate'
if getopt.flag == 'usesCurrent' then
getopt.usesCurrent = true
end
end
return text
end
local args = frame:getParent().args
local fields = {}
local isNamed = args.year or args.year1 or args.year2 or
args.month or args.month1 or args.month2 or
args.day or args.day1 or args.day2
if isNamed then
fields[1] = args.year1 or args.year
fields[2] = args.month1 or args.month
fields[3] = args.day1 or args.day
fields[4] = args.year2
fields[5] = args.month2
fields[6] = args.day2
else
for i = 1, 6 do
fields[i] = args[i]
end
end
local imax = 0
for i = 1, 6 do
fields[i] = stripToNil(fields[i])
if fields[i] then
imax = i
end
if getopt.omitZero and i % 3 ~= 1 then -- omit zero months and days as unknown values but keep year 0 which is 1 BCE
if tonumber(fields[i]) == 0 then
fields[i] = nil
getopt.partial = true
end
end
end
local fix = getopt.fix and 'fix' or ''
local noDefault = imax == 0 and getopt.noMissing
local partialText = getopt.partial and 'partial' or ''
local dates = {}
if isNamed or imax >= 3 then
local nrDates = getopt.single and 1 or 2
if getopt.wantMixture then
-- Cannot be partial since empty fields are set from current.
local components = { 'year', 'month', 'day' }
for i = 1, nrDates * 3 do
fields[i] = fields[i] or currentDate[components[i > 3 and i - 3 or i]]
end
for i = 1, nrDates do
local index = i == 1 and 1 or 4
dates[i] = Date(fields[index], fields[index+1], fields[index+2])
end
else
-- If partial dates are allowed, accept
-- year only, or
-- year and month only
-- Do not accept year and day without a month because that makes no sense
-- (and because, for example, Date('partial', 2001, nil, 12) sets day = nil, not 12).
for i = 1, nrDates do
local index = i == 1 and 1 or 4
local y, m, d = fields[index], fields[index+1], fields[index+2]
if (getopt.partial and y and (m or not d)) or (y and m and d) then
dates[i] = Date(fix, partialText, y, m, d)
elseif not y and not m and not d and not noDefault then
dates[i] = Date(flagCurrent())
end
end
end
elseif not noDefault then
getopt.textdates = true -- have parsed each date from a single text field
dates[1] = Date(fix, partialText, flagCurrent(fields[1]))
if not getopt.single then
dates[2] = Date(fix, partialText, flagCurrent(fields[2]))
end
end
if not dates[1] then
return message('需要有效的年月日')
end
if getopt.single then
return dates[1]
end
if not dates[2] then
return message('第二个日期应该是年月日')
end
return dates[1], dates[2]
end
local function ageGeneric(frame)
-- Return the result required by the specified template.
-- Can use sortable=x where x = on/table/off/debug in any supported template.
-- Some templates default to sortable=on but can be overridden.
local name = frame.args.template
if not name then
return message('调用它的模板必须有“|template=x”参数,其中x是所需的操作')
end
local args = frame:getParent().args
local specs = {
-- 重点!切勿随意更改!
age_days = { -- {{age in days}}
show = 'd',
disp = 'disp_raw',
},
age_days_nts = { -- {{age in days nts}}
show = 'd',
disp = 'disp_raw',
format = 'format_commas',
sortable = 'on',
},
duration_days = { -- {{duration in days}}
show = 'd',
disp = 'disp_raw',
duration = true,
},
duration_days_nts = { -- {{duration in days nts}}
show = 'd',
disp = 'disp_raw',
format = 'format_commas',
sortable = 'on',
duration = true,
},
age_full_years = { -- {{age}}
show = 'y',
abbr = 'abbr_raw',
flag = 'usesCurrent',
omitZero = true,
range = 'no',
},
age_full_years_nts = { -- {{age nts}}
show = 'y',
abbr = 'abbr_raw',
format = 'format_commas',
sortable = 'on',
},
age_in_years = { -- {{age in years}}
show = 'y',
abbr = 'abbr_raw',
negative = 'error',
range = 'dash',
},
age_in_years_nts = { -- {{age in years nts}}
show = 'y',
abbr = 'abbr_raw',
negative = 'error',
range = 'dash',
format = 'format_commas',
sortable = 'on',
},
age_infant = { -- {{age for infant}}
-- Do not set show because special processing is done later.
abbr = 'abbr_off',
disp = 'disp_age',
sortable = 'on',
age = true,
},
age_m = { -- {{age in months}}
show = 'm',
disp = 'disp_raw',
},
age_w = { -- {{age in weeks}}
show = 'w',
disp = 'disp_raw',
},
age_wd = { -- {{age in weeks and days}}
show = 'wd',
},
age_yd = { -- {{age in years and days}}
show = 'yd',
format = 'format_commas',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
age = true,
},
age_yd_nts = { -- {{age in years and days nts}}
show = 'yd',
format = 'format_commas',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
sortable = 'on',
age = true,
},
age_ym = { -- {{age in years and months}}
show = 'ym',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
},
age_ymd = { -- {{age in years, months and days}}
show = 'ymd',
range = 'dash',
},
age_ymwd = { -- {{age in years, months, weeks and days}}
show = 'ymwd',
wantMixture = true,
},
}
local spec = specs[name]
if not spec then
return message('指定的模板名称无效')
end
if name == 'age_days' then
local su = stripToNil(args['show unit'])
if su then
if su == 'abbr' or su == 'full' then
spec.disp = nil
spec.abbr = su == 'abbr' and 'abbr_on' or nil
end
end
end
local partial, autofill
local range = stripToNil(args.range) or spec.range
if range then
-- Suppose partial dates are used and age could be 11 or 12 years.
-- "|range=" (empty value) has no effect (spec is used).
-- "|range=yes" or spec.range == true sets range = true (gives "11或12")
-- "|range=dash" or spec.range == 'dash' sets range = 'dash' (gives "11—12").
-- "|range=no" or spec.range == 'no' sets range = nil and fills each date in the diff (gives "12").
-- ("on" is equivalent to "yes", and "off" is equivalent to "no").
-- "|range=OTHER" sets range = nil and rejects partial dates.
range = ({ dash = 'dash', off = 'no', no = 'no', [true] = true })[range] or yes(range)
if range then
partial = true -- accept partial dates with a possible age range for the result
if range == 'no' then
autofill = true -- missing month/day in first or second date are filled from other date or 1
range = nil
end
end
end
local getopt = {
fix = yes(args.fix),
flag = stripToNil(args.flag) or spec.flag,
omitZero = spec.omitZero,
partial = partial,
wantMixture = spec.wantMixture,
}
local date1, date2 = getDates(frame, getopt)
if type(date1) == 'string' then
return date1
end
local useAge = spec.age
if args.age ~= nil then
useAge = yes(args.age, spec.age)
end
local format = stripToNil(args.format)
local spell = spellOptions[format]
if format then
format = 'format_' .. format
elseif name == 'age_days' and getopt.textdates then
format = 'format_commas'
end
local parms = {
diff = date2:subtract(date1, { fill = autofill }),
wantDuration = spec.duration or yes(args.duration),
range = range,
wantSc = yes(args.sc),
show = args.show == 'hide' and 'hide' or spec.show,
abbr = useAge and 'abbr_age' or spec.abbr,
disp = spec.disp,
extra = (getopt.usesCurrent and format ~= 'format_raw') and '<span class="currentage"></span>' or nil,
format = format or spec.format,
round = yes(args.round),
sep = spec.sep,
sortable = translateParameters.sortable[args.sortable or spec.sortable],
spell = spell,
}
if (spec.negative or frame.args.negative) == 'error' and parms.diff.isnegative then
return message('第二个日期不应该在第一个日期之前')
end
return dateDifference(parms)
end
local function bda(frame)
-- Implement [[Template:Birth date and age]].
local args = frame:getParent().args
local options = { noMissing=true, single=true }
local date = getDates(frame, options)
if type(date) == 'string' then
return date -- error text
end
local Date = getExports(frame)
local diff = Date('currentdate') - date
if diff.isnegative or diff.years > 150 then
return message('计算年龄所需的出生日期无效')
end
local disp, show = 'disp_raw', 'y'
if diff.years < 2 then
disp = 'disp_age'
if diff.years == 0 and diff.months == 0 then
show = 'd'
else
show = 'm'
end
end
local result = '%-Y年%B月%-d日'
result = '(<span class="bday">%-Y-%m-%d</span>) </span>' .. result
result = '<span style="display:none"> ' ..
date:text(result) ..
'<span class="noprint ForceAgeToShow"> ' ..
'(' ..
dateDifference({
diff = diff,
show = show,
abbr = 'abbr_off',
disp = disp,
sep = 'sep_space',
}) ..
')</span>'
local warnings = tonumber(frame.args.warnings)
if warnings and warnings > 0 then
local good = {
df = true,
mf = true,
day = true,
day1 = true,
month = true,
month1 = true,
year = true,
year1 = true,
}
local invalid
local imax = options.textdates and 1 or 3
for k, _ in pairs(args) do
if type(k) == 'number' then
if k > imax then
invalid = tostring(k)
break
end
else
if not good[k] then
invalid = k
break
end
end
end
if invalid then
result = result .. message(invalid .. '参数无效', 'warning')
end
end
return result
end
local function dateToGsd(frame)
-- Implement [[Template:Gregorian serial date]].
-- Return Gregorian serial date of the given date, or the current date.
-- The returned value is negative for dates before 1 January 1 AD
-- despite the fact that GSD is not defined for such dates.
local date = getDates(frame, { wantMixture=true, single=true })
if type(date) == 'string' then
return date
end
return tostring(date.gsd)
end
local function jdToDate(frame)
-- Return formatted date from a Julian date.
-- The result includes a time if the input includes a fraction.
-- The word 'Julian' is accepted for the Julian calendar.
local Date = getExports(frame)
local args = frame:getParent().args
local date = Date('juliandate', args[1], args[2])
if date then
return date:text()
end
return message('需要有效的儒略历日期')
end
local function dateToJd(frame)
-- Return Julian date (a number) from a date which may include a time,
-- or the current date ('currentdate') or current date and time ('currentdatetime').
-- The word 'Julian' is accepted for the Julian calendar.
local Date = getExports(frame)
local args = frame:getParent().args
local date = Date(args[1], args[2], args[3], args[4], args[5], args[6], args[7])
if date then
return tostring(date.jd)
end
return message('需要有效的年/月/日或“currentdate”(当前)')
end
local function timeInterval(frame)
-- Implement [[Template:Time interval]].
-- There are two positional arguments: date1, date2.
-- The default for each is the current date and time.
-- Result is date2 - date1 formatted.
local Date = getExports(frame)
local args = frame:getParent().args
local parms = {
wantDuration = yes(args.duration),
range = yes(args.range) or (args.range == 'dash' and 'dash' or nil),
wantSc = yes(args.sc),
}
local fix = yes(args.fix) and 'fix' or ''
local date1 = Date(fix, 'partial', stripToNil(args[1]) or 'currentdatetime')
if not date1 then
return message('第一个参数中的开始日期无效')
end
local date2 = Date(fix, 'partial', stripToNil(args[2]) or 'currentdatetime')
if not date2 then
return message('第二个参数中的结束日期无效')
end
parms.diff = date2 - date1
for argname, translate in pairs(translateParameters) do
local parm = stripToNil(args[argname])
if parm then
parm = translate[parm]
if parm == nil then -- test for nil because false is a valid setting
return message('参数' .. argname .. '=' .. args[argname] .. '无效')
end
parms[argname] = parm
end
end
if parms.round then
local round = parms.round
local show = parms.show
if round ~= 'on' then
if show then
if show.id ~= round then
return message('参数show=' .. args.show .. '与round=' .. args.round .. '冲突')
end
else
parms.show = translateParameters.show[round]
end
end
parms.round = true
end
return dateDifference(parms)
end
return {
age_generic = ageGeneric, -- can emulate several age templates
birth_date_and_age = bda, -- Template:Birth_date_and_age
gsd = dateToGsd, -- Template:Gregorian_serial_date
extract = dateExtract, -- Template:Extract
jd_to_date = jdToDate, -- Template:?
JULIANDAY = dateToJd, -- Template:JULIANDAY
time_interval = timeInterval, -- Template:Time_interval
}
e3336fa0f7d460d6f03e7ba089b8b58632a537e8
Module:High-use
828
114
222
2024-04-22T15:31:11Z
zhwp>蕭漫
0
Scribunto
text/plain
local p = {}
local _fetch = require('Module:Transclusion_count').fetch
local nspn = mw.getCurrentFrame():preprocess('{{Namespace pagename}}')
local _separated_entries = require('Module:Separated entries').main
function p.num(frame, count)
if count == nil then count = _fetch(frame) end
-- Build output string
local return_value = ""
if count == nil then
if frame.args[1] == "risk" then
return_value = "大量頁面"
else
return_value = "許多頁面"
end
else
-- Use 2 significant figures for smaller numbers and 3 for larger ones
local sigfig = 2
if count >= 100000 then
sigfig = 3
end
-- Prepare to round to appropriate number of sigfigs
local f = math.floor(math.log10(count)) - sigfig + 1
-- Round and insert "approximately" or "+" when appropriate
if (frame.args[2] == "yes") or (mw.ustring.sub(frame.args[1],-1) == "+") then
-- Round down
return_value = string.format("%s+個頁面", mw.getContentLanguage():formatNum(math.floor( (count / 10^(f)) ) * (10^(f))) )
else
-- Round to nearest
return_value = string.format("約%s個頁面", mw.getContentLanguage():formatNum(math.floor( (count / 10^(f)) + 0.5) * (10^(f))) )
end
-- Insert percent of pages
if frame.args["all-pages"] and frame.args["all-pages"] ~= "" then
local percent = math.floor( ( (count/frame:callParserFunction('NUMBEROFPAGES', 'R') ) * 100) + 0.5)
return_value = string.format("%s,佔全部頁面的%s%%", return_value, percent)
end
end
return return_value
end
-- Actions if there is a large (greater than or equal to 100,000) transclusion count
function p.risk(frame)
local return_value = ""
if frame.args[1] == "risk" then
return_value = "risk"
else
local count = _fetch(frame)
if count and count >= 100000 then return_value = "risk" end
end
return return_value
end
function p.text(frame, count)
local bot_text = "\n\n----\n<small>模板引用數量會自動更新。</small>"
if frame.args["nobot"] == "true" then
bot_text = ""
end
if count == nil then count = _fetch(frame) end
local return_value = {}
local title = mw.title.getCurrentTitle()
local isdemo = false
if frame.args["demo"] and frame.args["demo"] ~= "" then
isdemo = true
title = mw.title.new(frame.args["demo"], "Template")
end
if title.subpageText == "doc" or title.subpageText == "sandbox" or title.subpageText == "testcases" then
title = title.basePageTitle
end
local templatecount = string.format("https://templatecount.toolforge.org/index.php?lang=zh&namespace=%s&name=%s", title.namespace,mw.uri.encode(title.text))
local used_on_text = string.format("'''%s被引用於[%s %s]'''",
(isdemo and "[["..title.fullText.."]]") or ("此"..nspn),
templatecount,
p.num(frame, count)
)
local sandbox_text = _separated_entries({
string.format("[[%s/sandbox|'''沙盒''']]", title.fullText),
string.format("[[%s/testcases|'''測試樣例''']]", title.fullText),
(title.namespace == 828 and "" or "[[Special:Mypage/沙盒|'''您的沙盒''']]"),
separator="、",
conjunction="或"
})
local info = ""
if frame.args["info"] and frame.args["info"] ~= "" then
info = "<br />" .. frame.args["info"]
end
sandbox_text = string.format("。%s<br /><small>為了避免造成大規模的影響,所有對此%s的編輯應先於%s上測試。</small>",
info, nspn, sandbox_text
)
local discussion_text = string.format("<br /><small>測試後無誤的版本可以一次性地加入此%s中,但是修改前請務必於", nspn)
if frame.args["2"] and frame.args["2"] ~= "" and frame.args["2"] ~= "yes" then
discussion_text = string.format("%s'''[[%s]]'''", discussion_text, frame.args["2"])
else
discussion_text = string.format("%s[[%s|'''討論頁''']]", discussion_text, title.talkPageTitle.fullText )
end
return table.concat({used_on_text, sandbox_text, discussion_text, "發起討論。</small>", bot_text})
end
function p.main(frame)
local count = _fetch(frame)
local return_value = ""
local image = "[[File:Ambox warning yellow.svg|40px|alt=警告|link=]]"
local type_param = "style"
if (frame.args[1] == "risk" or (count and count >= 100000) ) then
image = "[[File:Ambox warning orange.svg|40px|alt=警告|link=]]"
type_param = "content"
end
if frame.args["form"] == "editnotice" then
return_value = frame:expandTemplate{
title = 'editnotice',
args = {
["image"] = image,
["text"] = p.text(frame, count),
["expiry"] = (frame.args["expiry"] or "")
}
}
else
return_value = frame:expandTemplate{
title = 'ombox',
args = {
["type"] = type_param,
["image"] = image,
["text"] = p.text(frame, count),
["expiry"] = (frame.args["expiry"] or "")
}
}
end
return return_value
end
return p
6384bf0a00fa775731ab7d150a48c3516b9d5ee7
Template:Intricate template
10
198
414
2024-04-22T17:29:56Z
zhwp>蕭漫
0
wikitext
text/x-wiki
{{ombox
| type = style
| image = [[File:Ambox warning yellow.svg|40px|alt=|link=]]
| text = '''本模板含有複雜而精密的扩展语法。'''<br/><small>編輯本模板前,建議您先熟悉[[Help:解析器函数|解析器函數]]与本模板的设计思路、运作原理等。若您的編輯引發了意外的問題,請儘快[[Wikipedia:回退|撤銷]]編輯,因為本模板可能被大量頁面使用。<br/>您所作的编辑可先在<span class="nowraplinks">{{#switch:
{{#ifexist:{{FULLPAGENAME}}/sandbox |sandbox |
{{#ifexist:{{FULLPAGENAME}}/Sandbox |Sandbox |
{{#ifexist:{{FULLPAGENAME}}/test sandbox|test sandbox|
{{#ifexist:{{FULLPAGENAME}}/Test sandbox|Test sandbox|
{{#ifexist:{{FULLPAGENAME}}/test |test |
{{#ifexist:{{FULLPAGENAME}}/Test |Test |
}} }} }} }} }} }}
| sandbox = [[Template:{{PAGENAME}}/sandbox |本模板的沙盒]]
| Sandbox = [[Template:{{PAGENAME}}/Sandbox |/Sandbox子頁面]]
| test sandbox = [[Template:{{PAGENAME}}/test sandbox|/test sandbox子頁面]]
| Test sandbox = [[Template:{{PAGENAME}}/Test sandbox|/Test sandbox子頁面]]
| test = [[Template:{{PAGENAME}}/test |/test子頁面]]
| Test = [[Template:{{PAGENAME}}/Test |/Test子頁面]]
| #default = [[Template:沙盒 |模板沙盒]]
<!--ENDswitch-->}}</span>或您的[[Help:用户页|个人页面]]中进行測試。</small>
}}<includeonly>{{#ifeq: {{PAGENAME}} | {{BASEPAGENAME}} | [[Category:精密模板]] }}</includeonly><noinclude>
{{Documentation}}<!--
请将分类添加至模板文档页面,跨语言链接添加至维基数据页面。
請將分類添加至模板文件頁面,跨語言連結添加至Wikidata頁面。
--></noinclude>
b582208e633dcae9032dc9243179a7f3c21c7e11
那艺娜维基:Columns
4
24
43
2024-04-30T17:12:32Z
zhwp>Cookai1205
0
wikitext
text/x-wiki
<templatestyles src="Columns/styles.css" /><table class="multicol skin-nightmode-reset-color" style="{{#switch:{{{align|}}}
|left|right=float:{{{align}}}
|center=margin:0.5em auto
}};border-spacing:0;background:{{{background|{{{bgcol|transparent}}}}}};{{#if:{{{text-align|}}}|text-align:{{{text-align}}};}}{{{style|}}}" role="presentation">
<tr style="vertical-align:top;">
<td style="width:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col1style|}}};">{{#ifeq:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col1}}}</td>
{{#if:{{{col2<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col2style|}}};">{{#ifeq:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col2}}}</td>
}}{{#if:{{{col3<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col3style|}}};">{{#ifeq:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col3}}}</td>
}}{{#if:{{{col4<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col4style|}}};">{{#ifeq:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col4}}}</td>
}}{{#if:{{{col5<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col5style|}}};">{{#ifeq:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col5}}}</td>
}}{{#if:{{{col6<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col6style|}}};">{{#ifeq:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col6}}}</td>
}}{{#if:{{{col7<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col7style|}}};">{{#ifeq:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col7}}}</td>
}}{{#if:{{{col8<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col8style|}}};">{{#ifeq:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col8}}}</td>
}}{{#if:{{{col9<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col9style|}}};">{{#ifeq:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col9}}}</td>
}}{{#if:{{{col10<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col10style|}}};">{{#ifeq:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col10}}}</td>
}}
</tr></table><noinclude>{{Documentation}}</noinclude>
3c43118d7fdd34f4c2eeb0eb1de02303f4435f19
Template:Columns
10
52
97
2024-04-30T17:12:32Z
zhwp>Cookai1205
0
wikitext
text/x-wiki
<templatestyles src="Columns/styles.css" /><table class="multicol skin-nightmode-reset-color" style="{{#switch:{{{align|}}}
|left|right=float:{{{align}}}
|center=margin:0.5em auto
}};border-spacing:0;background:{{{background|{{{bgcol|transparent}}}}}};{{#if:{{{text-align|}}}|text-align:{{{text-align}}};}}{{{style|}}}" role="presentation">
<tr style="vertical-align:top;">
<td style="width:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col1style|}}};">{{#ifeq:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col1}}}</td>
{{#if:{{{col2<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col2style|}}};">{{#ifeq:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col2}}}</td>
}}{{#if:{{{col3<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col3style|}}};">{{#ifeq:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col3}}}</td>
}}{{#if:{{{col4<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col4style|}}};">{{#ifeq:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col4}}}</td>
}}{{#if:{{{col5<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col5style|}}};">{{#ifeq:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col5}}}</td>
}}{{#if:{{{col6<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col6style|}}};">{{#ifeq:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col6}}}</td>
}}{{#if:{{{col7<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col7style|}}};">{{#ifeq:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col7}}}</td>
}}{{#if:{{{col8<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col8style|}}};">{{#ifeq:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col8}}}</td>
}}{{#if:{{{col9<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col9style|}}};">{{#ifeq:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col9}}}</td>
}}{{#if:{{{col10<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col10style|}}};">{{#ifeq:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col10}}}</td>
}}
</tr></table><noinclude>{{Documentation}}</noinclude>
3c43118d7fdd34f4c2eeb0eb1de02303f4435f19
Template:Language icon
10
184
374
2024-05-02T12:27:50Z
zhwp>Shizhao
0
wikitext
text/x-wiki
{{#ifexist:Template:ISO 639 name {{{1<noinclude>|</noinclude>}}}
|<span style="font-family: sans-serif; cursor: default; color:var(--color-subtle, #54595d); font-size: 0.8em; bottom: 0.1em; font-weight: bold;" title="{{ISO 639 name {{{1}}}}}">({{{2|{{ISO 639 name |{{{1}}}}}}}})</span><!-- {{category handler
|main={{#ifeq:{{{1|}}}|en||[[Category:含有{{ISO 639 name {{{1}}}}}外部連結的條目]]}}
}} -->
|{{error|不正確的語言代碼。}}([[Template:Language_icon|說明]])如果在角色介紹看到此訊息,請參考'''[{{fullurl:夏目友人帳|diff=prev&oldid=34291294}} 這個條目]'''修改原始碼。[[Category:語言標示模板參數錯誤的頁面]]
}}<noinclude>
{{documentation}}
</noinclude>
02eda12992651a026fc38ca646527b54ba5e9928
Template:About/doc
10
120
234
2024-05-14T13:43:29Z
zhwp>TGTON
0
維護清理
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Categories go where indicated at the bottom of this page, please; interwikis go to Wikidata (see also: [[那艺娜维基:Wikidata]]). -->
{{High-risk|8925}}
{{ombox|type=content|text=本模板应在若干页面的名称彼此非常相似时使用,注意请勿滥用。}}
{{Lua|Module:About}}
{{Tlc|About}} 是维基百科中较常用的[[那艺娜维基:頂註|顶注模板]],应当被放置在条目顶端,引导有需要的读者去阅读其他名称相似的页面,使用范例如下:
*{{Tlx|About|Use1}} → {{About|Use1}}
*{{Tlx|About|Use1|<nowiki/>|Article2}} → {{About|Use1||Article2}}
*{{Tlx|About|Use1|<nowiki/>|Article2|和|Article3}} → {{About|Use1||Article2|和|Article3}}
*{{Tlx|About|Use1|Use2|Article2}} → {{About|Use1|Use2|Article2}}
*{{Tlx|About|Use1|Use2|Article2|和|Article3}} → {{About|Use1|Use2|Article2|和|Article3}}
*{{Tlx|About|Use1|Use2|Article2|其他用法}} → {{About|Use1|Use2|Article2|其他用法}}
本模板亦可放置在章节/小节顶端,此时需加入 <code>section=yes</code> 参数:
*{{Tlx|About|Use1|<nowiki>section=yes</nowiki>}} → {{About|Use1|section=yes}}
*{{Tlx|About|Use1|<nowiki/>|Article2|<nowiki>section=yes</nowiki>}} → {{About|Use1||Article2|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|和|Article3|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|和|Article3|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|其他用法|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|其他用法|section=yes}}
本模板同时支持可选参数 {{para|text}},用於添加自定义文字,请务必在其他题注模板无法满足需要时再使用该参数。
==重定向==
*{{Tl|Otheruses4}}
*{{Tl|关于}}
*{{Tl|關於}}
{{Hatnote templates}}
==模板參數==
{{TemplateDataHeader}}
{| class="wikitable sortable"
!colspan=2| 參數
! 描述
! 類型
! 狀態
|-
! 頁面描述
| <code>1</code>
| What the page this template is placed on is about ("This page is about …")
| 字串
| '''必填'''
|-
! 另一頁描述
| <code>2</code>
| What the first other page is about. If unused or blank, defaults to "For other uses".
| 字串
| 建議
|-
! 另一頁標題
| <code>3</code>
| The title of the first other page. If unused, defaults to "[page title] (disambiguation)".
| 頁面
| 建議
|-
! 另二頁描述
| <code>4</code>
| What the second other page is about.
| 字串
| 選填
|-
! 另二頁標題
| <code>5</code>
| The title of the second other page. If unused or blank and parameter 4 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! 另三頁描述
| <code>6</code>
| What the third other page is about.
| 字串
| 選填
|-
! 另三頁標題
| <code>7</code>
| The title of the third other page. If unused or blank and parameter 6 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! 另四頁描述
| <code>8</code>
| What the fourth other page is about.
| 字串
| 選填
|-
! 另四頁標題
| <code>9</code>
| The title of the fourth other page. If unused or blank and parameter 8 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! Custom text
| <code>section</code>
| Pass "yes" in this parameter to get wording appropriate for use at the top of a section.
;'''Bold text'''
;<code>yes</code>
| 字串
| 選填
|-
! 自定義文本
| <code>text</code>
| Text to be appended to the end.
| 字串
| 選填
|}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:消歧义与重定向模板]]
[[Category:顶注模板]]
}}</includeonly><noinclude>[[en:template:About/doc]]</noinclude>
57b9501b52db8b8be1d4d7483234fc5994d3c528
Module:InfoboxImage
828
214
446
2024-06-19T09:07:09Z
zhwp>Shizhao
0
Scribunto
text/plain
-- 输入: - 輸入:
-- image - 纯文件名(带有File:/Image:前缀与否皆可)或完全格式化的图片链接 - 純檔案名(帶有File:/Image:字首與否皆可)或完全格式化的圖片連結
-- page - page to display for multipage images (DjVu)
-- size - 显示图像大小 - 顯示影像大小
-- maxsize - 图像最大大小 - 影像最大大小
-- sizedefault - 如果size参数留空,默认显示图像大小 - 如果size參數留空,預設顯示影像大小
-- alt - 图像替换文本 - 影像替換文字
-- title - 图像标题文本 - 影像標題文字
-- border - 有边框则设为yes - 有邊框則設為yes
-- center - 图像需居中则设为yes - 影像需居中則設為yes
-- upright - 垂直图像参数 - 垂直影像參數
-- suppressplaceholder - 设为yes则检查图像是否为占位符并停用 - 設為yes則檢查影像是否為佔位符並停用
-- link - 点击图像时访问的页面 - 點選影像時訪問的頁面
-- 输出: - 輸出:
-- 格式化图像 - 格式化影像
-- 详情请参阅"Module:InfoboxImage/doc"页面 - 詳情請參閱"Module:InfoboxImage/doc"頁面
local i = {};
local placeholder_image = {
"Blue - Replace this image female.svg",
"Blue - Replace this image male.svg",
"Female no free image yet.png",
"Flag of None (square).svg",
"Flag of None.svg",
"Flag of.svg",
"Green - Replace this image female.svg",
"Green - Replace this image male.svg",
"Image is needed female.svg",
"Image is needed male.svg",
"Location map of None.svg",
"Male no free image yet.png",
"Missing flag.png",
"No flag.svg",
"No free portrait.svg",
"No portrait (female).svg",
"No portrait (male).svg",
"Red - Replace this image female.svg",
"Red - Replace this image male.svg",
"Replace this image female (blue).svg",
"Replace this image female.svg",
"Replace this image male (blue).svg",
"Replace this image male.svg",
"Silver - Replace this image female.svg",
"Silver - Replace this image male.svg",
"Replace this image.svg",
"Cricket no pic.png",
"CarersLogo.gif",
"Diagram Needed.svg",
"Example.jpg",
"Image placeholder.png",
"No male portrait.svg",
"Nocover-upload.png",
"NoDVDcover copy.png",
"Noribbon.svg",
"No portrait-BFD-test.svg",
"Placeholder barnstar ribbon.png",
"Project Trains no image.png",
"Image-request.png",
"Sin bandera.svg",
"Sin escudo.svg",
"Replace this image - temple.png",
"Replace this image butterfly.png",
"Replace this image.svg",
"Replace this image1.svg",
"Resolution angle.png",
"Image-No portrait-text-BFD-test.svg",
"Insert image here.svg",
"No image available.png",
"NO IMAGE YET square.png",
"NO IMAGE YET.png",
"No Photo Available.svg",
"No Screenshot.svg",
"No-image-available.jpg",
"Null.png",
"PictureNeeded.gif",
"Place holder.jpg",
"Unbenannt.JPG",
"UploadACopyrightFreeImage.svg",
"UploadAnImage.gif",
"UploadAnImage.svg",
"UploadAnImageShort.svg",
"CarersLogo.gif",
"Diagram Needed.svg",
"No male portrait.svg",
"NoDVDcover copy.png",
"Placeholder barnstar ribbon.png",
"Project Trains no image.png",
"Image-request.png",
}
function i.IsPlaceholder(image)
-- change underscores to spaces
image = mw.ustring.gsub(image, "_", " ");
assert(image ~= nil, 'mw.ustring.gsub(image, "_", " ") must not return nil')
-- if image starts with [[ then remove that and anything after |
if mw.ustring.sub(image,1,2) == "[[" then
image = mw.ustring.sub(image,3);
image = mw.ustring.gsub(image, "([^|]*)|.*", "%1");
assert(image ~= nil, 'mw.ustring.gsub(image, "([^|]*)|.*", "%1") must not return nil')
end
-- Trim spaces
image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
assert(image ~= nil, "mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1') must not return nil")
-- remove prefix if exists
local allNames = mw.site.namespaces[6].aliases
allNames[#allNames + 1] = mw.site.namespaces[6].name
allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
for i, name in ipairs(allNames) do
if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
break
end
end
-- Trim spaces
image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
-- capitalise first letter
image = mw.ustring.upper(mw.ustring.sub(image,1,1)) .. mw.ustring.sub(image,2);
for i,j in pairs(placeholder_image) do
if image == j then
return true
end
end
return false
end
function i.InfoboxImage(frame)
local image = frame.args["image"];
if image == "" or image == nil then
return "";
end
if image == " " then
return image;
end
if frame.args["suppressplaceholder"] ~= "no" then
if i.IsPlaceholder(image) == true then
return "";
end
end
if mw.ustring.lower(mw.ustring.sub(image,1,5)) == "http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "[http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[[http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "https:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[https:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,8)) == "[[https:" then
return "";
end
if mw.ustring.sub(image,1,2) == "[[" then
-- search for thumbnail images and add to tracking cat if found
if mw.title.getCurrentTitle().namespace == 0 and (mw.ustring.find(image, "|%s*thumb%s*[|%]]") or mw.ustring.find(image, "|%s*thumbnail%s*[|%]]")) then
return image .. "[[Category:信息框內使用縮圖語法的頁面]]";
elseif mw.title.getCurrentTitle().namespace == 0 then
return image .. "[[Category:使用过时图像语法的页面]]";
else
return image;
end
elseif mw.ustring.sub(image,1,2) == "{{" and mw.ustring.sub(image,1,3) ~= "{{{" then
return image;
elseif mw.ustring.sub(image,1,1) == "<" then
return image;
elseif mw.ustring.sub(image,1,5) == mw.ustring.char(127).."UNIQ" then
-- Found strip marker at begining, so pass don't process at all
return image;
elseif mw.ustring.sub(image,4,9) == "`UNIQ-" then
-- Found strip marker at begining, so pass don't process at all
return image;
else
local result = "";
local page = frame.args["page"];
local size = frame.args["size"];
local maxsize = frame.args["maxsize"];
local sizedefault = frame.args["sizedefault"];
local alt = frame.args["alt"];
local link = frame.args["link"];
local title = frame.args["title"];
local border = frame.args["border"];
local upright = frame.args["upright"] or "";
local thumbtime = frame.args["thumbtime"] or "";
local center= frame.args["center"];
local class= frame.args["class"];
-- remove prefix if exists
local allNames = mw.site.namespaces[6].aliases
allNames[#allNames + 1] = mw.site.namespaces[6].name
allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
for i, name in ipairs(allNames) do
if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
break
end
end
if maxsize ~= "" and maxsize ~= nil then
-- if no sizedefault then set to maxsize
if sizedefault == "" or sizedefault == nil then
sizedefault = maxsize
end
-- check to see if size bigger than maxsize
if size ~= "" and size ~= nil then
local sizenumber = tonumber(mw.ustring.match(size,"%d*")) or 0;
local maxsizenumber = tonumber(mw.ustring.match(maxsize,"%d*")) or 0;
if sizenumber>maxsizenumber and maxsizenumber>0 then
size = maxsize;
end
end
end
-- add px to size if just a number
if (tonumber(size) or 0) > 0 then
size = size .. "px";
end
-- add px to sizedefault if just a number
if (tonumber(sizedefault) or 0) > 0 then
sizedefault = sizedefault .. "px";
end
result = "[[File:" .. image;
if page ~= "" and page ~= nil then
result = result .. "|page=" .. page;
end
if size ~= "" and size ~= nil then
result = result .. "|" .. size;
elseif sizedefault ~= "" and sizedefault ~= nil then
result = result .. "|" .. sizedefault;
else
result = result .. "|frameless";
end
if center == "yes" then
result = result .. "|center"
end
if alt ~= "" and alt ~= nil then
result = result .. "|alt=" .. alt;
end
if link ~= "" and link ~= nil then
result = result .. "|link=" .. link;
end
if border == "yes" then
result = result .. "|border";
end
if upright == "yes" then
result = result .. "|upright";
elseif upright ~= "" then
result = result .. "|upright=" .. upright;
end
if thumbtime ~= "" then
result = result .. "|thumbtime=" .. thumbtime;
end
if title ~= "" and title ~= nil then
result = result .. "|" .. title;
elseif alt ~= "" and alt ~= nil then
result = result .. "|" .. alt;
end
if class ~= "" and class ~= nil then
result = result .. "|class=" .. class;
end
result = result .. "]]";
return result;
end
end
return i;
380eaec865b1a2e3d7a275c7823a72768fbbdaa4
Module:Infobox
828
130
256
2024-06-19T09:44:36Z
zhwp>Shizhao
0
Scribunto
text/plain
--
-- This module implements {{Infobox}}
-- 中文的此模块对比英文维基多解析了overimage, overcaption,
-- overimagerowclass以及header/labal/data*style参数。
--
local p = {}
local navbar = require('Module:Navbar')._navbar
local args = {}
local origArgs = {}
local root
local function notempty( s ) return s and s:match( '%S' ) end
local function fixChildBoxes(sval, tt)
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- the next two lines add a newline at the end of lists for the PHP parser
-- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&oldid=849054481
-- remove when [[:phab:T191516]] is fixed or OBE
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1')
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1')
return s
else
return sval
end
end
local function union(t1, t2)
-- Returns the union of the values of two tables, as a sequence.
local vals = {}
for k, v in pairs(t1) do
vals[v] = true
end
for k, v in pairs(t2) do
vals[v] = true
end
local ret = {}
for k, v in pairs(vals) do
table.insert(ret, k)
end
return ret
end
local function getArgNums(prefix)
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix was 'data', and
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local nums = {}
for k, v in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end
local function addRow(rowArgs)
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
if rowArgs.header and rowArgs.header ~= '_BLANK_' then
root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(rowArgs.rowstyle)
:attr('id', rowArgs.rowid)
:tag('th')
:attr('colspan', 2)
:attr('id', rowArgs.headerid)
:addClass(rowArgs.class)
:addClass(args.headerclass)
:css('text-align', 'center')
:cssText(rowArgs.headerstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.header, 'th'))
if rowArgs.data then
root:wikitext('[[Category:使用已忽略数据行信息框模板的条目]]')
end
elseif rowArgs.data then
if not rowArgs.data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then
rowArgs.rowstyle = 'display:none'
end
local row = root:tag('tr')
row:addClass(rowArgs.rowclass)
row:cssText(rowArgs.rowstyle)
row:attr('id', rowArgs.rowid)
if rowArgs.label then
row
:tag('th')
:attr('scope', 'row')
:css('text-align', 'left')
:attr('id', rowArgs.labelid)
:cssText(rowArgs.labelstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end
local dataCell = row:tag('td')
if not rowArgs.label then
dataCell
:attr('colspan', 2)
:css('text-align', 'center')
end
dataCell
:attr('id', rowArgs.dataid)
:addClass(rowArgs.class)
:cssText(rowArgs.datastyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.data, 'td'))
end
end
local function renderOverImage()
if not args.overimage then return end
local row = root:tag('tr')
row:addClass(args.overimagerowclass)
local topImage = row:tag('td')
topImage:attr('colspan', 2)
topImage:addClass(args.imageclass)
topImage:cssText(args.imagestyle)
topImage:css('text-align', 'center')
if args.overcaption and args.captionstyle then
topImage:wikitext(fixChildBoxes(args.overimage .. '<div style=\"' .. args.captionstyle .. '\">' .. args.overcaption .. '</div>', 'td'))
else
if args.overcaption then
topImage:wikitext(fixChildBoxes(args.overimage .. '<div>' .. args.overcaption .. '</div>', 'td'))
else
topImage:wikitext(fixChildBoxes(args.overimage, 'td'))
end
end
end
local function renderTitle()
if not args.title then return end
root
:tag('caption')
:addClass(args.titleclass)
:cssText(args.titlestyle)
:wikitext('\'\'\'' .. args.title .. '\'\'\'')
end
local function renderAboveRow()
if not args.above then return end
root
:tag('tr')
:tag('th')
:attr('colspan', 2)
:addClass(args.aboveclass)
:css('text-align', 'center')
:css('font-size', '125%')
:css('font-weight', 'bold')
:cssText(args.abovestyle)
:wikitext(fixChildBoxes(args.above,'th'))
end
local function renderBelowRow()
if not args.below then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass(args.belowclass)
:css('text-align', 'center')
:cssText(args.belowstyle)
:wikitext(fixChildBoxes(args.below,'td'))
end
local function renderSubheaders()
if args.subheader then
args.subheader1 = args.subheader
end
if args.subheaderrowclass then
args.subheaderrowclass1 = args.subheaderrowclass
end
local subheadernums = getArgNums('subheader')
for k, num in ipairs(subheadernums) do
addRow({
data = args['subheader' .. tostring(num)],
datastyle = args.subheaderstyle,
rowcellstyle = args['subheaderstyle' .. tostring(num)],
class = args.subheaderclass,
rowclass = args['subheaderrowclass' .. tostring(num)]
})
end
end
local function renderImages()
if args.image then
args.image1 = args.image
end
if args.caption then
args.caption1 = args.caption
end
local imagenums = getArgNums('image')
for k, num in ipairs(imagenums) do
local caption = args['caption' .. tostring(num)]
local data = mw.html.create():wikitext(args['image' .. tostring(num)])
if caption then
data
:tag('div')
:cssText(args.captionstyle)
:wikitext(caption)
end
addRow({
data = tostring(data),
datastyle = args.imagestyle,
class = args.imageclass,
rowclass = args['imagerowclass' .. tostring(num)]
})
end
end
local function preprocessRows()
-- Gets the union of the header and data argument numbers,
-- and renders them all in order using addRow.
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
local lastheader
for k, num in ipairs(rownums) do
if args['header' .. tostring(num)] then
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
lastheader = num
elseif args['data' .. tostring(num)] and args['data' .. tostring(num)]:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then
local data = args['data' .. tostring(num)]
if data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('%S') then
lastheader = nil
end
end
end
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
end
local function renderRows()
-- Gets the union of the header and data argument numbers,
-- and renders them all in order using addRow.
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
for k, num in ipairs(rownums) do
addRow({
header = args['header' .. tostring(num)],
headerstyle = (args.headerstyle or '') .. (args.headerstyle and ';' or '') .. (args['header' .. tostring(num) .. 'style'] or ''),
label = args['label' .. tostring(num)],
labelstyle = (args.labelstyle or '') .. (args.labelstyle and ';' or '') .. (args['label' .. tostring(num) .. 'style'] or ''),
data = args['data' .. tostring(num)],
datastyle = (args.datastyle or '') .. (args.datastyle and ';' or '') .. (args['data' .. tostring(num) .. 'style'] or ''),
class = args['class' .. tostring(num)],
rowclass = args['rowclass' .. tostring(num)],
rowstyle = args['rowstyle' .. tostring(num)],
rowcellstyle = args['rowcellstyle' .. tostring(num)],
dataid = args['dataid' .. tostring(num)],
labelid = args['labelid' .. tostring(num)],
headerid = args['headerid' .. tostring(num)],
rowid = args['rowid' .. tostring(num)]
})
end
end
local function renderNavBar()
if not args.name then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:css('text-align', 'right')
:wikitext(navbar{
args.name,
mini = 1,
})
end
local function renderItalicTitle()
local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
end
end
local function renderTrackingCategories()
if args.decat ~= 'yes' then
if args.child == 'yes' then
if args.title then
root:wikitext('[[Category:使用带有标题参数的嵌入式信息框模板的条目]]')
end
elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
root:wikitext('[[Category:使用无数据行信息框模板的条目]]')
end
end
end
local function _infobox()
-- Specify the overall layout of the infobox, with special settings
-- if the infobox is used as a 'child' inside another infobox.
if args.child ~= 'yes' then
root = mw.html.create('table')
root
:addClass((args.subbox ~= 'yes') and 'infobox' or nil)
:addClass(args.bodyclass)
:attr('cellspacing', 3)
:css('border-spacing', '3px')
if args.subbox == 'yes' then
root
:css('padding', '0')
:css('border', 'none')
:css('margin', '-3px')
:css('width', 'auto')
:css('min-width', '100%')
:css('font-size', '88%')
:css('clear', 'none')
:css('float', 'none')
:css('background-color', 'transparent')
:css('color', 'inherit')
else
root
:css('width', '22em')
:css('text-align', 'left')
:css('font-size', '88%')
:css('line-height', '1.5em')
end
root
:cssText(args.bodystyle)
renderTitle()
renderAboveRow()
else
root = mw.html.create()
root
:wikitext(args.title)
end
renderOverImage()
renderSubheaders()
renderImages()
if args.autoheaders then
preprocessRows()
end
renderRows()
renderBelowRow()
renderNavBar()
renderItalicTitle()
renderTrackingCategories()
return tostring(root)
end
local function preprocessSingleArg(argName)
-- If the argument exists and isn't blank, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
if origArgs[argName] and origArgs[argName] ~= '' then
args[argName] = origArgs[argName]
end
end
local function preprocessArgs(prefixTable, step)
-- Assign the parameters with the given prefixes to the args table, in order, in batches
-- of the step size specified. This is to prevent references etc. from appearing in the
-- wrong order. The prefixTable should be an array containing tables, each of which has
-- two possible fields, a "prefix" string and a "depend" table. The function always parses
-- parameters containing the "prefix" string, but only parses parameters in the "depend"
-- table if the prefix parameter is present and non-blank.
if type(prefixTable) ~= 'table' then
error("Non-table value detected for the prefix table", 2)
end
if type(step) ~= 'number' then
error("Invalid step value detected", 2)
end
-- Get arguments without a number suffix, and check for bad input.
for i,v in ipairs(prefixTable) do
if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
error('Invalid input detected to preprocessArgs prefix table', 2)
end
preprocessSingleArg(v.prefix)
-- Only parse the depend parameter if the prefix parameter is present and not blank.
if args[v.prefix] and v.depend then
for j, dependValue in ipairs(v.depend) do
if type(dependValue) ~= 'string' then
error('Invalid "depend" parameter value detected in preprocessArgs')
end
preprocessSingleArg(dependValue)
end
end
end
-- Get arguments with number suffixes.
local a = 1 -- Counter variable.
local moreArgumentsExist = true
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a, a + step - 1 do
for j,v in ipairs(prefixTable) do
local prefixArgName = v.prefix .. tostring(i)
if origArgs[prefixArgName] then
moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
preprocessSingleArg(prefixArgName)
end
-- Process the depend table if the prefix argument is present and not blank, or
-- we are processing "prefix1" and "prefix" is present and not blank, and
-- if the depend table is present.
if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
for j,dependValue in ipairs(v.depend) do
local dependArgName = dependValue .. tostring(i)
preprocessSingleArg(dependArgName)
end
end
end
end
a = a + step
end
end
function preprocessSpecificStyle(styleTable, step)
-- Assign the parameters *style to the args table
local a = 1 -- Counter variable.
local moreArgumentsExist = true
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a,a + step - 1 do
for j,v in ipairs(styleTable) do
local styleArgName = v.arg .. tostring(i) .. 'style'
if origArgs[styleArgName] then
moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
preprocessSingleArg(styleArgName)
end
end
end
a = a + step
end
end
local function parseDataParameters()
-- Parse the data parameters in the same order that the old {{infobox}} did, so that
-- references etc. will display in the expected places. Parameters that depend on
-- another parameter are only processed if that parameter is present, to avoid
-- phantom references appearing in article reference lists.
preprocessSingleArg('autoheaders')
preprocessSingleArg('child')
preprocessSingleArg('bodyclass')
preprocessSingleArg('subbox')
preprocessSingleArg('bodystyle')
preprocessSingleArg('overimage')
preprocessSingleArg('overcaption')
preprocessSingleArg('overimagerowclass')
preprocessSingleArg('title')
preprocessSingleArg('titleclass')
preprocessSingleArg('titlestyle')
preprocessSingleArg('above')
preprocessSingleArg('aboveclass')
preprocessSingleArg('abovestyle')
preprocessArgs({
{prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}
}, 10)
preprocessSingleArg('subheaderstyle')
preprocessSingleArg('subheaderclass')
preprocessArgs({
{prefix = 'image', depend = {'caption', 'imagerowclass'}}
}, 10)
preprocessSingleArg('captionstyle')
preprocessSingleArg('imagestyle')
preprocessSingleArg('imageclass')
preprocessArgs({
{prefix = 'header'},
{prefix = 'data', depend = {'label'}},
{prefix = 'rowclass'},
{prefix = 'rowstyle'},
{prefix = 'rowcellstyle'},
{prefix = 'class'},
{prefix = 'dataid'},
{prefix = 'labelid'},
{prefix = 'headerid'},
{prefix = 'rowid'}
}, 80)
preprocessSpecificStyle({
{arg = 'header'},
{arg = 'label'},
{arg = 'data'}
}, 80)
preprocessSingleArg('headerclass')
preprocessSingleArg('headerstyle')
preprocessSingleArg('labelstyle')
preprocessSingleArg('datastyle')
preprocessSingleArg('below')
preprocessSingleArg('belowclass')
preprocessSingleArg('belowstyle')
preprocessSingleArg('name')
args['italic title'] = origArgs['italic title'] -- different behaviour if blank or absent
preprocessSingleArg('decat')
end
function p.infobox(frame)
-- If called via #invoke, use the args passed into the invoking template.
-- Otherwise, for testing purposes, assume args are being passed directly in.
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end
parseDataParameters()
return _infobox()
end
function p.infoboxTemplate(frame)
-- For calling via #invoke within a template
origArgs = {}
for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end
parseDataParameters()
return _infobox()
end
return p
b1241aab87afb6394aa68f97f9f73cef0fa25fa0
那艺娜维基:Shortcut/styles.css
4
20
35
2024-06-20T02:42:46Z
zhwp>Shizhao
0
sanitized-css
text/css
.shortcutbox {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.shortcutbox-left {
float:left;
}
.shortcutbox-ombox {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.shortcut-anchordiv {
position:relative;
top:-3em;
}
.module-shortcutboxplain {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.module-shortcutboxplain-left {
float:left;
}
.module-omboxshortcutplain {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.module-shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.module-shortcutanchordiv {
position:relative;
top:-3em;
}
9c4ef4c581a945084d5e44c5b35135cef5ea8c27
Template:Shortcut/styles.css
10
46
85
2024-06-20T02:42:46Z
zhwp>Shizhao
0
sanitized-css
text/css
.shortcutbox {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.shortcutbox-left {
float:left;
}
.shortcutbox-ombox {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.shortcut-anchordiv {
position:relative;
top:-3em;
}
.module-shortcutboxplain {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.module-shortcutboxplain-left {
float:left;
}
.module-omboxshortcutplain {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.module-shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.module-shortcutanchordiv {
position:relative;
top:-3em;
}
9c4ef4c581a945084d5e44c5b35135cef5ea8c27
Module:Yesno
828
28
51
2024-06-24T20:51:11Z
zhwp>Xiplus-abot
0
已保护“[[Module:Yesno]]”:高風險模板:3127208引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to the template {{yesno}}.
return function (val, default)
-- If your wiki uses non-ascii characters for any of "yes", "no", etc., you
-- should replace "val:lower()" with "mw.ustring.lower(val)" in the
-- following line.
val = type(val) == 'string' and val:lower() or val
if val == nil then
return nil
elseif val == true
or val == 'yes'
or val == 'y'
or val == 'true'
or val == 't'
or val == 'on'
or val == '是'
or val == '开'
or val == '開'
or tonumber(val) == 1
then
return true
elseif val == false
or val == 'no'
or val == 'n'
or val == 'false'
or val == 'f'
or val == 'off'
or val == '否'
or val == '关'
or val == '關'
or tonumber(val) == 0
then
return false
else
return default
end
end
2f0635fe93a396f2633055bc8670ccb84f3caa50
Module:Arguments
828
30
55
2024-06-24T20:51:31Z
zhwp>Xiplus-abot
0
已保护“[[Module:Arguments]]”:高風險模板:3971931引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
-- This module provides easy processing of arguments passed to Scribunto from
-- #invoke. It is intended for use by other Lua modules, and should not be
-- called from #invoke directly.
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local arguments = {}
-- Generate four different tidyVal functions, so that we don't have to check the
-- options every time we call it.
local function tidyValDefault(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
else
return val
end
else
return val
end
end
local function tidyValTrimOnly(key, val)
if type(val) == 'string' then
return val:match('^%s*(.-)%s*$')
else
return val
end
end
local function tidyValRemoveBlanksOnly(key, val)
if type(val) == 'string' then
if val:find('%S') then
return val
else
return nil
end
else
return val
end
end
local function tidyValNoChange(key, val)
return val
end
local function matchesTitle(given, title)
local tp = type( given )
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
end
local translate_mt = { __index = function(t, k) return k end }
function arguments.getArgs(frame, options)
checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}
--[[
-- Set up argument translation.
--]]
options.translate = options.translate or {}
if getmetatable(options.translate) == nil then
setmetatable(options.translate, translate_mt)
end
if options.backtranslate == nil then
options.backtranslate = {}
for k,v in pairs(options.translate) do
options.backtranslate[v] = k
end
end
if options.backtranslate and getmetatable(options.backtranslate) == nil then
setmetatable(options.backtranslate, {
__index = function(t, k)
if options.translate[k] ~= k then
return nil
else
return k
end
end
})
end
--[[
-- Get the argument tables. If we were passed a valid frame object, get the
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
-- on the options set and on the parent frame's availability. If we weren't
-- passed a valid frame object, we are being called from another Lua module
-- or from the debug console, so assume that we were passed a table of args
-- directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
if options.wrappers then
--[[
-- The wrappers option makes Module:Arguments look up arguments in
-- either the frame argument table or the parent argument table, but
-- not both. This means that users can use either the #invoke syntax
-- or a wrapper template without the loss of performance associated
-- with looking arguments up in both the frame and the parent frame.
-- Module:Arguments will look up arguments in the parent frame
-- if it finds the parent frame's title in options.wrapper;
-- otherwise it will look up arguments in the frame object passed
-- to getArgs.
--]]
local parent = frame:getParent()
if not parent then
fargs = frame.args
else
local title = parent:getTitle():gsub('/sandbox$', '')
local found = false
if matchesTitle(options.wrappers, title) then
found = true
elseif type(options.wrappers) == 'table' then
for _,v in pairs(options.wrappers) do
if matchesTitle(v, title) then
found = true
break
end
end
end
-- We test for false specifically here so that nil (the default) acts like true.
if found or options.frameOnly == false then
pargs = parent.args
end
if not found or options.parentOnly == false then
fargs = frame.args
end
end
else
-- options.wrapper isn't set, so check the other options.
if not options.parentOnly then
fargs = frame.args
end
if not options.frameOnly then
local parent = frame:getParent()
pargs = parent and parent.args or nil
end
end
if options.parentFirst then
fargs, pargs = pargs, fargs
end
else
luaArgs = frame
end
-- Set the order of precedence of the argument tables. If the variables are
-- nil, nothing will be added to the table, which is how we avoid clashes
-- between the frame/parent args and the Lua args.
local argTables = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs
--[[
-- Generate the tidyVal function. If it has been specified by the user, we
-- use that; if not, we choose one of four functions depending on the
-- options chosen. This is so that we don't have to call the options table
-- every time the function is called.
--]]
local tidyVal = options.valueFunc
if tidyVal then
if type(tidyVal) ~= 'function' then
error(
"bad value assigned to option 'valueFunc'"
.. '(function expected, got '
.. type(tidyVal)
.. ')',
2
)
end
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end
--[[
-- Set up the args, metaArgs and nilArgs tables. args will be the one
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
-- arguments are memoized in nilArgs, and the metatable connects all of them
-- together.
--]]
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
setmetatable(args, metatable)
local function mergeArgs(tables)
--[[
-- Accepts multiple tables as input and merges their keys and values
-- into one table. If a value is already present it is not overwritten;
-- tables listed earlier have precedence. We are also memoizing nil
-- values, which can be overwritten if they are 's' (soft).
--]]
for _, t in ipairs(tables) do
for key, val in pairs(t) do
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
local tidiedVal = tidyVal(key, val)
if tidiedVal == nil then
nilArgs[key] = 's'
else
metaArgs[key] = tidiedVal
end
end
end
end
end
--[[
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
-- and are only fetched from the argument tables once. Fetching arguments
-- from the argument tables is the most resource-intensive step in this
-- module, so we try and avoid it where possible. For this reason, nil
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
-- in the metatable of when pairs and ipairs have been called, so we do not
-- run pairs and ipairs on the argument tables more than once. We also do
-- not run ipairs on fargs and pargs if pairs has already been run, as all
-- the arguments will already have been copied over.
--]]
metatable.__index = function (t, key)
--[[
-- Fetches an argument when the args table is indexed. First we check
-- to see if the value is memoized, and if not we try and fetch it from
-- the argument tables. When we check memoization, we need to check
-- metaArgs before nilArgs, as both can be non-nil at the same time.
-- If the argument is not present in metaArgs, we also check whether
-- pairs has been run yet. If pairs has already been run, we return nil.
-- This is because all the arguments will have already been copied into
-- metaArgs by the mergeArgs function, meaning that any other arguments
-- must be nil.
--]]
if type(key) == 'string' then
key = options.translate[key]
end
local val = metaArgs[key]
if val ~= nil then
return val
elseif metatable.donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs(argTables) do
local argTableVal = tidyVal(key, argTable[key])
if argTableVal ~= nil then
metaArgs[key] = argTableVal
return argTableVal
end
end
nilArgs[key] = 'h'
return nil
end
metatable.__newindex = function (t, key, val)
-- This function is called when a module tries to add a new value to the
-- args table, or tries to change an existing value.
if type(key) == 'string' then
key = options.translate[key]
end
if options.readOnly then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; the table is read-only',
2
)
elseif options.noOverwrite and args[key] ~= nil then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; overwriting existing arguments is not permitted',
2
)
elseif val == nil then
--[[
-- If the argument is to be overwritten with nil, we need to erase
-- the value in metaArgs, so that __index, __pairs and __ipairs do
-- not use a previous existing value, if present; and we also need
-- to memoize the nil in nilArgs, so that the value isn't looked
-- up in the argument tables if it is accessed again.
--]]
metaArgs[key] = nil
nilArgs[key] = 'h'
else
metaArgs[key] = val
end
end
local function translatenext(invariant)
local k, v = next(invariant.t, invariant.k)
invariant.k = k
if k == nil then
return nil
elseif type(k) ~= 'string' or not options.backtranslate then
return k, v
else
local backtranslate = options.backtranslate[k]
if backtranslate == nil then
-- Skip this one. This is a tail call, so this won't cause stack overflow
return translatenext(invariant)
else
return backtranslate, v
end
end
end
metatable.__pairs = function ()
-- Called when pairs is run on the args table.
if not metatable.donePairs then
mergeArgs(argTables)
metatable.donePairs = true
end
return translatenext, { t = metaArgs }
end
local function inext(t, i)
-- This uses our __index metamethod
local v = t[i + 1]
if v ~= nil then
return i + 1, v
end
end
metatable.__ipairs = function (t)
-- Called when ipairs is run on the args table.
return inext, t, 0
end
return args
end
return arguments
3134ecce8429b810d445e29eae115e2ae4c36c53
Module:Documentation
828
97
188
2024-06-24T20:53:21Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation]]”:高風險模板:32360引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[那艺娜维基:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[那艺娜维基:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[那艺娜维基:Template documentation|documentation]]
-- is [[那艺娜维基:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[那艺娜维基:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2c374c042ebd8bc4d2d63d207aa078459069c065
262
188
2024-06-24T20:53:21Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation]]”:高風險模板:32360引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[那艺娜维基:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[那艺娜维基:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[那艺娜维基:Template documentation|documentation]]
-- is [[那艺娜维基:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[那艺娜维基:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2c374c042ebd8bc4d2d63d207aa078459069c065
380
262
2024-06-24T20:53:21Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation]]”:高風險模板:32360引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[Wikipedia:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[Wikipedia:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[Wikipedia:Template documentation|documentation]]
-- is [[Wikipedia:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2af87750dfe917f0a57a35d5eda6623dceda1d6f
Template:Sandbox other
10
102
198
2024-06-24T20:53:31Z
zhwp>Xiplus-abot
0
已保护“[[Template:Sandbox other]]”:高風險模板:6867引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
{{#if:{{#ifeq:{{SUBPAGENAME}}|sandbox|1}}{{#invoke:String|match|{{PAGENAME}}|/sandbox/styles.css$|plain=false|nomatch=}}|{{{1|}}}|{{{2|}}}}}<!--
--><noinclude>{{documentation}}</noinclude>
3462b190d62e7d7ed1a408cd5607c5c124a1ce15
Sandbox other
0
293
609
2024-06-24T20:53:31Z
zhwp>Xiplus-abot
0
已保护“[[Template:Sandbox other]]”:高風險模板:6867引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
{{#if:{{#ifeq:{{SUBPAGENAME}}|sandbox|1}}{{#invoke:String|match|{{PAGENAME}}|/sandbox/styles.css$|plain=false|nomatch=}}|{{{1|}}}|{{{2|}}}}}<!--
--><noinclude>{{documentation}}</noinclude>
3462b190d62e7d7ed1a408cd5607c5c124a1ce15
Template:Cmbox
10
251
519
2024-06-25T12:21:56Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<templatestyles src="Cmbox/style.css" />
{{#invoke:Message box|cmbox}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
b4b6273c788f27ebde512d666f392db572fabea8
Module:NoteTA
828
126
248
2024-06-26T10:05:38Z
zhwp>Shizhao
0
Scribunto
text/plain
local z = {}
local WikitextLC = require( 'Module:WikitextLC' )
function Tcode( args )
if args.T == nil or args.T == '' then
return ''
end
local div = mw.html.create( 'div' )
:attr( 'class', 'noteTA-title' )
:attr( 'data-noteta-code', args.T )
:wikitext( WikitextLC.title( args.T ) )
if args.dt ~= nil and args.dt ~= '' then
div:attr( 'data-noteta-desc', args.dt )
end
return tostring( div )
end
function group( name, frame )
if name == nil or name == '' then
return ''
end
local moduleTitle = mw.title.makeTitle( 'Module', 'CGroup/' .. name )
if moduleTitle and moduleTitle.exists then
local data = mw.loadData( 'Module:CGroup/' .. name )
local pieces = {}
if data.content then
for i, v in ipairs( data.content ) do
if v.type == 'item' and v.rule then
table.insert( pieces, '-{H|' .. v.rule .. '}-' )
end
end
return tostring( mw.html.create( 'div' )
:attr( 'data-noteta-group-source', 'module' )
:attr( 'data-noteta-group', data.name or name )
:wikitext( table.concat( pieces ) ) )
end
end
local templateTitle = mw.title.makeTitle( 'Template', 'CGroup/' .. name )
if templateTitle and templateTitle.exists then
return frame:expandTemplate{ title = templateTitle }
end
return tostring( mw.html.create( 'div' )
-- :attr( 'id', 'noteTA-group-' .. mw.uri.anchorEncode( name ) )
:attr( 'data-noteta-group-source', 'none' )
:attr( 'data-noteta-group', name ) )
end
function Gcode( args, frame )
local code = {}
for i = 1, 30 do
table.insert( code, group( args['G' .. i], frame ) )
end
code = table.concat( code )
if code ~= '' then
code = tostring( mw.html.create( 'div' )
:attr( 'class', 'noteTA-group' )
:wikitext( code ) )
if args.G31 ~= nil then
code = code .. '[[Category:NoteTA模板参数使用数量超过限制的页面|G]]'
end
end
return code
end
function local_( i, code, desc )
if code == nil or code == '' then
return ''
end
local div = mw.html.create( 'div' )
-- :attr( 'id', 'noteTA-local-' .. i )
:attr( 'data-noteta-code', code )
:wikitext( WikitextLC.hidden( code ) )
if desc ~= nil and desc ~= '' then
div:attr( 'data-noteta-desc', desc )
end
return tostring( div )
end
function Lcode( args )
local code = {}
for i = 1, 30 do
table.insert( code, local_( i, args[i], args['d' .. i] ) )
end
code = table.concat( code )
if code ~= '' then
code = tostring( mw.html.create( 'div' )
:attr( 'class', 'noteTA-local' )
:wikitext( code ) )
if args[31] ~= nil then
code = code .. '[[Category:NoteTA模板参数使用数量超过限制的页面|L]]'
end
end
return code
end
function z.main( frame )
local args
if frame == mw.getCurrentFrame() then
-- Being called from {{noteTA}}
args = frame:getParent().args
else
-- Being called from another module
args = frame
frame = mw.getCurrentFrame()
end
local Tc = Tcode( args )
local Gc = Gcode( args, frame )
local Lc = Lcode( args )
local code = Tc .. Gc .. Lc
if code ~= '' then
local hash = require( 'Module:Crc32lua' ).crc32( mw.dumpObject( args ) )
code = frame:extensionTag{
name = 'indicator',
content = '[[File:Zh conversion icon m.svg|35px|本页使用了标题或全文手工转换|link=|class=skin-invert]]',
args = { name = string.format( 'noteTA-%x', hash ) },
} .. tostring( mw.html.create( 'div' )
:attr( 'id', string.format( 'noteTA-%x', hash ) )
:attr( 'class', 'noteTA' )
:wikitext( code ) )
if mw.title.getCurrentTitle():inNamespace( 'Template' ) then
code = code .. '[[Category:放置于模板的noteTA]]'
end
end
return code
end
return z
ea994d54783b2d06cd967aa31f96f99dbef2b6b7
Module:Userbox
828
274
570
2024-06-29T13:48:24Z
zhwp>Shizhao
0
Scribunto
text/plain
-- This module implements {{userbox}}.
local categoryHandler = require('Module:Category handler').main
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function checkNum(val, default)
-- Checks whether a value is a number greater than or equal to zero. If so,
-- returns it as a number. If not, returns a default value.
val = tonumber(val)
if val and val >= 0 then
return val
else
return default
end
end
local function addSuffix(num, suffix)
-- Turns a number into a string and adds a suffix.
if num then
return tostring(num) .. suffix
else
return nil
end
end
local function checkNumAndAddSuffix(num, default, suffix)
-- Checks a value with checkNum and adds a suffix.
num = checkNum(num, default)
return addSuffix(num, suffix)
end
local function makeCat(cat, sort)
-- Makes a category link.
if sort then
return mw.ustring.format('[[Category:%s|%s]]', cat, sort)
else
return mw.ustring.format('[[Category:%s]]', cat)
end
end
--------------------------------------------------------------------------------
-- Argument processing
--------------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local origArgs = require('Module:Arguments').getArgs(frame)
local args = {}
for k, v in pairs(origArgs) do
args[k] = v
end
return p.main(funcName, args)
end
end
p.userbox = makeInvokeFunc('_userbox')
p['userbox-2'] = makeInvokeFunc('_userbox-2')
p['userbox-r'] = makeInvokeFunc('_userbox-r')
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.main(funcName, args)
local userboxData = p[funcName](args)
local userbox = p.render(userboxData)
local cats = p.categories(args)
return userbox .. (cats or '')
end
function p._userbox(args)
-- Does argument processing for {{userbox}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args[1] or args['border-c'] or args['id-c'] or '#999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
data.infoClass = args['info-class']
-- Get id values.
local id = args.logo or args[3] or args.id
data.id = id
data.showId = id and true or false
data.idWidth = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.idBackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.idTextAlign = args['id-a'] or 'center'
data.idFontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.idColor = args['logo-color'] or args['id-fc'] or data.infoColor
data.idPadding = args['logo-padding'] or args['id-p'] or '0 1px 0 0'
data.idLineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.idOtherParams = args['logo-other-param'] or args['id-op']
data.idClass = args['id-class']
return data
end
p['_userbox-2'] = function (args)
-- Does argument processing for {{userbox-2}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args[9] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args[1] or args['border-c'] or args['id1-c'] or '#999999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args[2] or args['info-c'] or '#eeeeee'
-- Get info values.
data.info = args[4] or args.info or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-s'], 8, 'pt')
data.infoColor = args[8] or args['info-fc'] or 'black'
data.infoPadding = args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-lh'] or '1.25em'
data.infoOtherParams = args['info-op']
-- Get id values.
data.showId = true
data.id = args.logo or args[3] or args.id1 or 'id1'
data.idWidth = checkNumAndAddSuffix(args['id1-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['id-h'], 45, 'px')
data.idBackgroundColor = args[1] or args['id1-c'] or '#dddddd'
data.idTextAlign = 'center'
data.idFontSize = checkNumAndAddSuffix(args['id1-s'], 14, 'pt')
data.idLineHeight = args['id1-lh'] or '1.25em'
data.idColor = args['id1-fc'] or data.infoColor
data.idPadding = args['id1-p'] or '0 1px 0 0'
data.idOtherParams = args['id1-op']
-- Get id2 values.
data.showId2 = true
data.id2 = args.logo or args[5] or args.id2 or 'id2'
data.id2Width = checkNumAndAddSuffix(args['id2-w'], 45, 'px')
data.id2Height = data.idHeight
data.id2BackgroundColor = args[7] or args['id2-c'] or args[1] or '#dddddd'
data.id2TextAlign = 'center'
data.id2FontSize = checkNumAndAddSuffix(args['id2-s'], 14, 'pt')
data.id2LineHeight = args['id2-lh'] or '1.25em'
data.id2Color = args['id2-fc'] or data.infoColor
data.id2Padding = args['id2-p'] or '0 0 0 1px'
data.id2OtherParams = args['id2-op']
return data
end
p['_userbox-r'] = function (args)
-- Does argument processing for {{userbox-r}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args[1] or args['border-c'] or args['id-c'] or '#999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'
-- Get id values.
data.showId = false -- We only show id2 in userbox-r.
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-align'] or args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
-- Get id2 values.
data.showId2 = true
data.id2 = args.logo or args[3] or args.id or 'id'
data.id2Width = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.id2Height = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.id2BackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.id2TextAlign = args['id-a'] or 'center'
data.id2FontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.id2Color = args['logo-color'] or args['id-fc'] or data.infoColor
data.id2Padding = args['logo-padding'] or args['id-p'] or '0 0 0 1px'
data.id2LineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.id2OtherParams = args['logo-other-param'] or args['id-op']
return data
end
function p.render(data)
-- Renders the userbox html using the content of the data table.
-- Render the div tag html.
local root = mw.html.create('div')
root
:css('float', data.float)
:css('border', (data.borderWidth or '') .. ' solid ' .. (data.borderColor or ''))
:css('margin', '1px')
:css('width', data.width)
:addClass('wikipediauserbox skin-invert ')
:addClass(data.bodyClass)
-- Render the table tag html.
local tableroot = root:tag('table')
tableroot
:attr('role', 'presentation')
:css('border-collapse', 'collapse')
:css('width', data.width)
:css('margin-bottom', '0')
:css('margin-top', '0')
:css('background', data.backgroundColor)
-- Render the id html.
local tablerow = tableroot:tag('tr')
if data.showId then
tablerow:tag('td')
:css('border', '0')
:css('width', data.idWidth)
:css('height', data.idHeight)
:css('background', data.idBackgroundColor)
:css('text-align', data.idTextAlign)
:css('font-size', data.idFontSize)
:css('font-weight', 'bold')
:css('color', data.idColor)
:css('padding', data.idPadding)
:css('line-height', data.idLineHeight)
:css('vertical-align', 'middle')
:cssText(data.idOtherParams)
:addClass(data.idClass)
:wikitext(data.id)
end
-- Render the info html.
tablerow:tag('td')
:css('border', '0')
:css('text-align', data.infoTextAlign)
:css('font-size', data.infoFontSize)
:css('padding', data.infoPadding)
:css('height', data.infoHeight)
:css('line-height', data.infoLineHeight)
:css('color', data.infoColor)
:css('vertical-align', 'middle')
:cssText(data.infoOtherParams)
:addClass(data.infoClass)
:wikitext(data.info)
-- Render the second id html.
if data.showId2 then
tablerow:tag('td')
:css('border', '0')
:css('width', data.id2Width)
:css('height', data.id2Height)
:css('background', data.id2BackgroundColor)
:css('text-align', data.id2TextAlign)
:css('font-size', data.id2FontSize)
:css('font-weight', 'bold')
:css('color', data.id2Color)
:css('padding', data.id2Padding)
:css('line-height', data.id2LineHeight)
:css('vertical-align', 'middle')
:cssText(data.id2OtherParams)
:wikitext(data.id2)
end
local title = mw.title.getCurrentTitle()
if (title.namespace == 2) and not title.text:match("/") then
return tostring(root) -- regular user page
elseif title.namespace == 14 then
return tostring(root) -- category
elseif title.isTalkPage then
return tostring(root) -- talk page
end
local legible = true
local contrast = require('Module:Color contrast')._ratio
local function has_text(wikitext)
local function get_alt(text)
return text:match("|alt=([^|]*)") or ""
end
wikitext = wikitext:gsub("]]", "|]]")
wikitext = wikitext:gsub("%[%[%s*[Mm][Ee][Dd][Ii][Aa]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ff][Ii][Ll][Ee]%s*:[^|]-(|.-)]]", get_alt)
return mw.text.trim(wikitext) ~= ""
end
if contrast { data.infoColor, data.backgroundColor, error = 0 } < 4.5 then
legible = false
end
if data.showId and contrast { data.idColor, data.idBackgroundColor, error = 0 } < 4.5 then
if has_text(data.id or "") then
legible = false
end
end
if data.showId2 and contrast { data.id2Color, data.id2BackgroundColor, error = 0 } < 4.5 then
if has_text(data.id2 or "") then
legible = false
end
end
if not legible then
root:wikitext('[[Category:可能难以辨认的用户框模板]]')
end
return tostring(root)
end
function p.categories(args, page)
-- Gets categories from [[Module:Category handler]].
-- The page parameter makes the function act as though the module was being called from that page.
-- It is included for testing purposes.
local cats = {}
cats[#cats + 1] = args.usercategory
cats[#cats + 1] = args.usercategory2
cats[#cats + 1] = args.usercategory3
if #cats > 0 then
-- Get the title object
local title
if page then
title = mw.title.new(page)
else
title = mw.title.getCurrentTitle()
end
-- Build category handler arguments.
local chargs = {}
chargs.page = page
chargs.nocat = args.nocat
chargs.main = '[[Category:未正確放置討論頁模板的頁面]]'
if args.notcatsubpages then
chargs.subpage = 'no'
end
-- User namespace.
local user = ''
for i, cat in ipairs(cats) do
user = user .. makeCat(cat)
end
chargs.user = user
-- Template namespace.
local basepage = title.baseText
local template = ''
for i, cat in ipairs(cats) do
template = template .. makeCat(cat, ' ' .. basepage)
end
chargs.template = template
return categoryHandler(chargs)
else
return nil
end
end
return p
f9c852070dccc2fa1ee92864d43a8d38cc9bfe76
Template:Template other
10
132
260
2024-06-29T20:51:28Z
zhwp>Xiplus-abot
0
已更改“[[Template:Template other]]”的保护设置:高風險模板:141414引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{lc: {{{demospace}}} }} <!--Use lower case "demospace"-->
| {{#ifeq:{{NAMESPACE}}|{{ns:Template}}
| template
| other
}}
}}
| template = {{{1|}}}
| other
| #default = {{{2|}}}
}}<!--End switch--><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
06fb13d264df967b5232141067eb7d2b67372d76
Module:Infobox/styles.css
828
136
280
2024-06-29T20:51:37Z
zhwp>Xiplus-abot
0
已更改“[[Module:Infobox/styles.css]]”的保护设置:高風險模板:144221引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
sanitized-css
text/css
/*
* This TemplateStyles sheet deliberately does NOT include the full set of
* infobox styles. We are still working to migrate all of the manual
* infoboxes. See [[MediaWiki talk:Common.css/to do#Infobox]]
* DO NOT ADD THEM HERE
*/
/*
* not strictly certain these styles are necessary since the modules now
* exclusively output infobox-subbox or infobox, not both
* just replicating the module faithfully
*/
.infobox-subbox {
padding: 0;
border: none;
margin: -3px;
width: auto;
min-width: 100%;
font-size: 100%;
clear: none;
float: none;
background-color: transparent;
}
.infobox-3cols-child {
margin: auto;
}
.infobox .navbar {
font-size: 100%;
}
/* T281642 */
body.skin-minerva .infobox-header,
body.skin-minerva .infobox-subheader,
body.skin-minerva .infobox-above,
body.skin-minerva .infobox-title,
body.skin-minerva .infobox-image,
body.skin-minerva .infobox-full-data,
body.skin-minerva .infobox-below {
text-align: center;
}
/* Dark theme: [[William_Wragg]], [[Coral_Castle]] */
html.skin-theme-clientpref-night .infobox-full-data:not(.notheme) > div:not(.notheme)[style] {
background: #1f1f23 !important;
/* switch with var( --color-base ) when supported. */
color: #f8f9fa;
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-full-data:not(.notheme) div:not(.notheme) {
background: #1f1f23 !important;
/* switch with var( --color-base ) when supported. */
color: #f8f9fa;
}
}
html.skin-theme-clientpref-night .infobox td div:not(.notheme)[style] {
background: transparent !important;
color: var(--color-base,#202122);
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox td div:not(.notheme)[style] {
background: transparent !important;
color: var(--color-base,#202122);
}
}
html.skin-theme-clientpref-night .infobox td div.NavHead:not(.notheme)[style] {
background: transparent !important;
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox td div.NavHead:not(.notheme)[style] {
background: transparent !important;
}
}
/* Since infobox is a table, many infobox templates take advantage of this to add columns and rows to the infobox itself rather than as part of a new table inside them. This class should be discouraged and removed on the long term, but allows us to at least identify these tables going forward
Currently in use on: [[Module:Infobox3cols]]
Fixes issue described in https://phabricator.wikimedia.org/F55300125 on Vector 2022.
*/
@media (min-width: 640px) {
body.skin--responsive .infobox-table {
display: table !important;
}
body.skin--responsive .infobox-table > caption {
display: table-caption !important;
}
body.skin--responsive .infobox-table > tbody {
display: table-row-group;
}
body.skin--responsive .infobox-table tr {
display: table-row !important;
}
body.skin--responsive .infobox-table th,
body.skin--responsive .infobox-table td {
padding-left: inherit;
padding-right: inherit;
}
}
6538c5ed546ba98bea13e31fe0117c4c56f572fd
Userboxtop
0
286
595
2024-06-30T09:00:34Z
zhwp>Shizhao
0
wikitext
text/x-wiki
{|name="userboxes" id="userboxes" style="margin-left: 0em; margin-right: 0em; margin-bottom: 0.5em; width: {{{width|248}}}px; border: {{{bordercolor|#99B3FF}}} solid 1px; background-color: {{{backgroundcolor|var(--background-color-base,#FFFFFF)}}}; color: {{{textcolor|var(--color-emphasized,#000000)}}}; float: {{{2|{{{align|right}}}}}}; {{{extra-css|}}}" class="vcard userboxes {{{extra-class|}}}"
|<div style="text-align: center; font-size: 120%; font-weight: bold;">{{{1|{{{toptext|<div class="fn">{{BASEPAGENAME}}</div>的[[Wikipedia:用戶框|用戶框]]}}}}}}</div><noinclude>
|}{{Documentation}}
</noinclude>
b653aebf2eda0153ba8eb482c67102d55cec15a3
Template:Userboxtop
10
298
619
2024-06-30T09:00:34Z
zhwp>Shizhao
0
wikitext
text/x-wiki
{|name="userboxes" id="userboxes" style="margin-left: 0em; margin-right: 0em; margin-bottom: 0.5em; width: {{{width|248}}}px; border: {{{bordercolor|#99B3FF}}} solid 1px; background-color: {{{backgroundcolor|var(--background-color-base,#FFFFFF)}}}; color: {{{textcolor|var(--color-emphasized,#000000)}}}; float: {{{2|{{{align|right}}}}}}; {{{extra-css|}}}" class="vcard userboxes {{{extra-class|}}}"
|<div style="text-align: center; font-size: 120%; font-weight: bold;">{{{1|{{{toptext|<div class="fn">{{BASEPAGENAME}}</div>的[[Wikipedia:用戶框|用戶框]]}}}}}}</div><noinclude>
|}{{Documentation}}
</noinclude>
b653aebf2eda0153ba8eb482c67102d55cec15a3
Template:Template shortcut
10
240
499
2024-06-30T12:57:06Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<div role="note" class="shortcutbox shortcutbox-left plainlist plainlinks noprint" style="<!--
-->{{#switch:{{{clear|}}} |true=clear:{{{float|right}}}; |left|right|both=clear:{{{clear|}}}; |#default=}}<!--
-->float: {{#ifeq:{{{float|}}}|left|left|right}};<!--
-->margin: {{{top|0em}}} {{#ifeq:{{{float|}}}|left|1em 0em 0em|0em 0em 1em}};<!--
-->border: 1px solid var(--border-color-base,#aaa); background: var(--background-color-base,#fff); padding: 0.3em 0.6em 0.2em 0.6em; text-align: center; font-size: 85%; font-weight: bold;color: inherit;"><!--
Adding the shortcut links:
--><div style="display: inline-block; border-bottom: 1px solid #aaa; line-height: 1.5em; font-weight: normal; margin-bottom: .2em;">{{#if:{{{redirect|}}} |重定向 |[[WP:捷徑|-{zh-hans:快捷方式; zh-hant:捷徑;}-]]}}</div> {{bulleted list
| {{#if: {{{1|<noinclude>{{PAGENAME}}</noinclude>}}} | {{{{{pre|}}}{{#ifexist:Template:{{{1}}} |[{{fullurl:Template:{{{1}}}|redirect=no}} {{#if:true|{{{1}}}}}] |[[Template:{{{1|<noinclude>{{PAGENAME}}</noinclude>}}}|{{#if:true|{{{1|<noinclude>{{PAGENAME}}</noinclude>}}}}}]]}}}} }}<!--
--> | {{#if:{{{2|}}} | {{{{{pre2|}}}{{#ifexist:Template:{{{2}}} |[{{fullurl:Template:{{{2}}}|redirect=no}} {{#if:true|{{{2}}}}}] |[[Template:{{{2}}}|{{#if:true|{{{2}}}}}]]}}}} }}<!--
--> | {{#if:{{{3|}}} | {{{{{pre3|}}}{{#ifexist:Template:{{{3}}} |[{{fullurl:Template:{{{3}}}|redirect=no}} {{#if:true|{{{3}}}}}] |[[Template:{{{3}}}|{{#if:true|{{{3}}}}}]]}}}} }}<!--
--> | {{#if:{{{4|}}} | {{{{{pre4|}}}{{#ifexist:Template:{{{4}}} |[{{fullurl:Template:{{{4}}}|redirect=no}} {{#if:true|{{{4}}}}}] |[[Template:{{{4}}}|{{#if:true|{{{4}}}}}]]}}}} }}<!--
--> | {{#if:{{{5|}}} | {{{{{pre5|}}}{{#ifexist:Template:{{{5}}} |[{{fullurl:Template:{{{5}}}|redirect=no}} {{#if:true|{{{5}}}}}] |[[Template:{{{5}}}|{{#if:true|{{{5}}}}}]]}}}} }}<!--
--> | {{#if:{{{6|}}} | {{{{{pre6|}}}{{#ifexist:Template:{{{6}}} |[{{fullurl:Template:{{{6}}}|redirect=no}} {{#if:true|{{{6}}}}}] |[[Template:{{{6}}}|{{#if:true|{{{6}}}}}]]}}}} }}<!--
--> | {{#if:{{{7|}}} | {{{{{pre7|}}}{{#ifexist:Template:{{{7}}} |[{{fullurl:Template:{{{7}}}|redirect=no}} {{#if:true|{{{7}}}}}] |[[Template:{{{7}}}|{{#if:true|{{{7}}}}}]]}}}} }}<!--
--> | {{#if:{{{8|}}} | {{{{{pre8|}}}{{#ifexist:Template:{{{8}}} |[{{fullurl:Template:{{{8}}}|redirect=no}} {{#if:true|{{{8}}}}}] |[[Template:{{{8}}}|{{#if:true|{{{8}}}}}]]}}}} }}<!--
--> | {{#if:{{{9|}}} | {{{{{pre9|}}}{{#ifexist:Template:{{{9}}} |[{{fullurl:Template:{{{9}}}|redirect=no}} {{#if:true|{{{9}}}}}] |[[Template:{{{9}}}|{{#if:true|{{{9}}}}}]]}}}} }}<!--
--> | {{#if:{{{10|}}} | {{{{{pre10|}}}{{#ifexist:Template:{{{10}}} |[{{fullurl:Template:{{{10}}}|redirect=no}} {{#if:true|{{{10}}}}}] |[[Template:{{{10}}}|{{#if:true|{{{10}}}}}]]}}}} }}<!--
-->}}<!--
--></div><noinclude>{{Documentation}}</noinclude>
27b5a406da826aed6d2cd54974d89d0d4da74869
Template:Block
10
317
659
2024-07-01T12:40:57Z
zhwp>Shizhao
0
wikitext
text/x-wiki
{{#if:{{NAMESPACE}}
| <!--
--><templatestyles src="Block/styles.css" /><!--
--><mark
class="skin-invert {{#switch: {{{4|{{{flag|}}}}}}
| sl = inline-text-block-sl
| hsd = inline-text-block-hsd
| hsl = inline-text-block-hsl
| inline-text-block-hd
}}"
title="{{#if: {{{2|}}} | {{{2}}} | 你知道的太多了}}"
style="background-color: {{#if: {{{color|{{{3|}}}}}}
| {{{color|{{{3}}}}}}
| {{#switch: {{{4}}}
| sl
| hsl = transparent
| #000000bf
}}
}}">{{{1}}}</mark>
| {{{1}}}
}}<noinclude>
{{Documentation}}</noinclude>
fcd75afadd7fc914e87c0bb8dcef2c6f6fd15a61
Template:Markup/row
10
196
410
2024-07-01T12:48:28Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<noinclude>{| style="width:90%;border-width:medium;"</noinclude> 
|-
|style="width:50%; background:var(--background-color-neutral-subtle,#f9f9f9); color: inherit;border-width:1px;border-style:solid none none solid;border-color:var(--border-color-muted,#ddd); padding:9px 5px 5px; vertical-align:top;"| <!--
-->{{#tag:pre |{{{c1|[markup]}}}|style="margin:0;border:none;padding:0; word-wrap:break-word; white-space:-moz-pre-wrap;white-space:-o-pre-wrap;white-space:-pre-wrap;white-space:pre-wrap; {{{c1style|}}}"}}
|style="width:50%; background:var(--background-color-neutral-subtle,#f9f9f9); color: inherit;border-width:1px;border-style:solid solid none solid;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:top;"| <!--
--><div style="{{{c2style|}}}">
{{{c2|[''rendering'']}}}
</div>
<!--
--><noinclude>
|-
|style="width:50%;border-width:1px;border-style:solid none none none;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:text-top;"|
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:text-top;"|
|-
|}</noinclude>
aa743127991adfc72d644b7a5fea77723e2e9c81
MediaWiki:Gadget-twinkleclose.js
8
168
338
2024-07-01T14:36:17Z
zhwp>Xiplus
0
Repo at 8bad8e1: Disable on vector-2022
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleclose.js: XFD closing module
****************************************
* Mode of invocation: Links after section heading
* Active on: AfD dated archive pages
* Config directives in: TwinkleConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.close = function twinkleclose() {
if (Twinkle.getPref('XfdClose') === 'hide' || !/^Wikipedia:(頁面|檔案)存廢討論\/記錄\/\d+\/\d+\/\d+$/.test(mw.config.get('wgPageName'))) {
return;
}
mw.hook('wikipage.content').add(function(item) {
if (item.attr('id') === 'mw-content-text') {
Twinkle.close.addLinks();
}
});
};
Twinkle.close.addLinks = function twinklecloseAddLinks() {
var prevH2Section = -1;
$('.mw-heading.mw-heading1, .mw-heading.mw-heading2, .mw-heading.mw-heading3, .mw-heading.mw-heading4, .mw-heading.mw-heading5, .mw-heading.mw-heading6', '#bodyContent').each(function (index, current) {
current.setAttribute('data-section', index + 1);
if ($(current).hasClass('mw-heading2')) {
prevH2Section = index + 1;
} else {
current.setAttribute('data-parent-section', prevH2Section);
}
});
var selector = ':has(a:only-of-type):not(:has(+ div.NavFrame))';
var titles = $('#bodyContent').find('.mw-heading2' + selector + ':not(:has(+ p + div.mw-heading.mw-heading3)), .mw-heading3' + selector);
titles.each(function(key, current) {
var $pageLink = $(current).find('h2 a, h3 a');
var headlinehref = $pageLink.attr('href');
if (headlinehref === undefined) {
return;
}
var title = null;
if (headlinehref.indexOf('redlink=1') !== -1) {
title = headlinehref.slice(19, -22);
} else {
var m = headlinehref.match(/\/wiki\/([^?]+)/, '$1');
if (m !== null) {
title = m[1];
}
}
if (title === null) {
return;
}
title = decodeURIComponent(title);
title = title.replace(/_/g, ' '); // Normalize for using in interface and summary
var pagenotexist = $pageLink.hasClass('new');
var section = current.getAttribute('data-section');
var parentSection = current.getAttribute('data-parent-section') || -1;
var node = current.getElementsByClassName('mw-editsection')[0];
var delDivider = document.createElement('span');
delDivider.appendChild(document.createTextNode(' | '));
node.insertBefore(delDivider, node.childNodes[1]);
var delLink = document.createElement('a');
delLink.className = 'twinkle-close-button';
delLink.href = '#';
delLink.setAttribute('data-section', section);
delLink.innerText = conv({ hans: '关闭讨论', hant: '關閉討論' });
$(delLink).on('click', function() {
Twinkle.close.callback(title, section, parentSection, pagenotexist);
return false;
});
node.insertBefore(delLink, node.childNodes[1]);
});
};
var date = new Morebits.date();
// Keep this synchronized with {{delh}}
Twinkle.close.codes = [{
key: conv({ hans: '请求无效', hant: '請求無效' }),
value: {
ir: {
label: conv({ hans: '请求无效', hant: '請求無效' }),
action: 'keep'
},
rep: {
label: conv({ hans: '重复提出,无效', hant: '重複提出,無效' }),
action: 'keep'
},
commons: {
label: conv({ hans: '应在维基共享资源提请', hant: '應在維基共享資源提請' }),
action: 'keep'
},
ne: {
label: conv({ hans: '目标页面或文件不存在,无效', hant: '目標頁面或檔案不存在,無效' }),
action: 'keep'
},
nq: {
label: conv({ hans: '提删者未获取提删资格,无效', hant: '提刪者未取得提刪資格,無效' }),
action: 'keep'
}
}
},
{
key: '保留',
value: {
k: {
label: '保留',
action: 'keep',
adminonly: true
},
sk: {
label: '快速保留',
action: 'keep'
},
tk: {
label: conv({ hans: '暂时保留,改挂维护模板(关注度等)', hant: '暫時保留,改掛維護模板(關注度等)' }),
value: conv({ hans: '暂时保留', hant: '暫時保留' }),
action: 'keep'
},
rr: {
label: conv({ hans: '请求理由消失', hant: '請求理由消失' }),
action: 'keep',
selected: Twinkle.getPref('XfdClose') === 'nonadminonly'
},
dan: {
label: conv({ hans: '删后重建', hant: '刪後重建' }),
action: 'keep',
adminonly: true
}
}
},
{
key: conv({ hans: '删除', hant: '刪除' }),
value: {
d: {
label: conv({ hans: '删除', hant: '刪除' }),
action: 'del',
adminonly: true,
selected: Twinkle.getPref('XfdClose') === 'all'
},
ic: {
label: conv({ hans: '图像因侵权被删', hant: '圖像因侵權被刪' }),
action: 'del',
adminonly: true
}
}
},
{
key: conv({ hans: '快速删除', hant: '快速刪除' }),
value: {
sd: {
label: conv({ hans: '快速删除', hant: '快速刪除' }),
action: 'del'
},
lssd: {
label: conv({ hans: '无来源或著作权信息,快速删除', hant: '無來源或版權資訊,快速刪除' }),
action: 'del'
},
svg: {
label: conv({ hans: '已改用SVG图形,快速删除', hant: '已改用SVG圖形,快速刪除' }),
action: 'del'
},
nowcommons: {
label: conv({ hans: '维基共享资源已提供,快速删除', hant: '維基共享資源已提供,快速刪除' }),
action: 'del'
},
drep: {
label: conv({ hans: '多次被删除,条目锁定', hant: '多次被刪除,條目鎖定' }),
action: 'del',
adminonly: true
}
}
},
{
key: conv({ hans: '转移至其他维基计划', hant: '轉移至其他維基計劃' }),
value: {
twc: {
label: conv({ hans: '转移至维基共享资源', hant: '轉移至維基共享資源' }),
action: 'noop',
adminonly: true
},
twn: {
label: conv({ hans: '转移至维基新闻', hant: '轉移至維基新聞' }),
action: 'noop',
adminonly: true
},
tws: {
label: conv({ hans: '转移至维基文库', hant: '轉移至維基文庫' }),
action: 'noop',
adminonly: true
},
twb: {
label: conv({ hans: '转移至维基教科书', hant: '轉移至維基教科書' }),
action: 'noop',
adminonly: true
},
twq: {
label: conv({ hans: '转移至维基语录', hant: '轉移至維基語錄' }),
action: 'noop',
adminonly: true
},
twt: {
label: conv({ hans: '转移至维基词典', hant: '轉移至維基詞典' }),
action: 'noop',
adminonly: true
},
twv: {
label: conv({ hans: '转移至维基学院', hant: '轉移至維基學院' }),
action: 'noop',
adminonly: true
},
twvoy: {
label: conv({ hans: '转移至维基导游', hant: '轉移至維基導遊' }),
action: 'noop',
adminonly: true
},
two: {
label: conv({ hans: '转移至其他维基计划', hant: '轉移至其他維基計劃' }),
action: 'noop',
adminonly: true
}
}
},
{
key: conv({ hans: '其他处理方法', hant: '其他處理方法' }),
value: {
relist: {
label: conv({ hans: '重新提交讨论', hant: '重新提交討論' }),
action: 'noop',
disabled: mw.config.get('wgPageName') === 'Wikipedia:頁面存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc'),
hidden: !/^Wikipedia:頁面存廢討論\/記錄\//.test(mw.config.get('wgPageName'))
},
c: {
label: conv({ hans: '转交侵权', hant: '轉交侵權' }),
action: 'noop'
},
m2ifd: {
label: conv({ hans: '转送文件存废讨论', hant: '轉送檔案存廢討論' }),
action: 'noop'
},
r: {
label: '重定向',
action: 'keep',
adminonly: true
},
cr: {
label: conv({ hans: '分类重定向', hant: '分類重定向' }),
action: 'keep',
adminonly: true
},
m: {
label: conv({ hans: '移动', hant: '移動' }),
action: 'keep',
adminonly: true
},
merge: {
label: conv({ hans: '并入', hant: '併入' }),
action: 'keep',
adminonly: true
},
mergeapproved: {
label: conv({ hans: '允许并入', hant: '允許併入' }),
action: 'keep',
adminonly: true
},
nc: {
label: conv({ hans: '无共识暂时保留', hant: '無共識暫時保留' }),
value: conv({ hans: '无共识', hant: '無共識' }),
action: 'keep'
}
}
}];
Twinkle.close.callback = function twinklecloseCallback(title, section, parentSection, noop) {
var Window = new Morebits.simpleWindow(410, 200);
Window.setTitle(conv({ hans: '关闭存废讨论', hant: '關閉存廢討論' }) + ' \u00B7 ' + title);
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '存废讨论设置', hant: '存廢討論設定' }), 'WP:TW/PREF#close');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#close');
var form = new Morebits.quickForm(Twinkle.close.callback.evaluate);
if ($('.skin-vector-2022').length > 0) {
mw.notify(conv({ hans: '关闭存废讨论功能暂不支持 Vector 2022,请改用其他外观。', hant: '關閉存廢討論功能暫不支援 Vector 2022,請改用其他外觀。' }), { type: 'error' });
form.append({
type: 'div',
label: conv({ hans: '关闭存废讨论功能暂不支持 Vector 2022,请改用其他外观。', hant: '關閉存廢討論功能暫不支援 Vector 2022,請改用其他外觀。' })
});
var result2 = form.render();
Window.setContent(result2);
Window.display();
return;
}
form.append({
type: 'select',
label: conv({ hans: '处理结果:', hant: '處理結果:' }),
name: 'sub_group',
event: Twinkle.close.callback.change_code
});
form.append({
type: 'input',
name: 'sdreason',
label: conv({ hans: '速删理由:', hant: '速刪理由:' }),
tooltip: conv({ hans: '用于删除日志,使用{{delete}}的参数格式,例如 A1 或 A1|G1', hant: '用於刪除日誌,使用{{delete}}的參數格式,例如 A1 或 A1|G1' }),
hidden: true
});
form.append({
type: 'input',
name: 'remark',
label: conv({ hans: '补充说明:', hant: '補充說明:' })
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '只关闭讨论,不进行其他操作', hant: '只關閉討論,不進行其他操作' }),
value: 'noop',
name: 'noop',
event: Twinkle.close.callback.change_operation,
checked: noop
}
]
});
if (new mw.Title(title).namespace % 2 === 0 && new mw.Title(title).namespace !== 2) { // hide option for user pages, to avoid accidentally deleting user talk page
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除关联的讨论页', hant: '刪除關聯的討論頁' }),
value: 'talkpage',
name: 'talkpage',
tooltip: conv({ hans: '删除时附带删除此页面的讨论页。', hant: '刪除時附帶刪除此頁面的討論頁。' }),
checked: true,
event: function(event) {
event.stopPropagation();
}
}
]
});
}
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除重定向页', hant: '刪除重新導向頁面' }),
value: 'redirects',
name: 'redirects',
tooltip: conv({ hans: '删除到此页的重定向。', hant: '刪除到此頁的重新導向。' }),
checked: true,
event: function(event) {
event.stopPropagation();
}
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
var sub_group = result.getElementsByTagName('select')[0]; // hack
var resultData = {
title: title,
section: parseInt(section),
parentSection: parseInt(parentSection),
noop: noop
};
$(result).data('resultData', resultData);
// worker function to create the combo box entries
var createEntries = function(contents, container) {
$.each(contents, function(itemKey, itemProperties) {
var key = typeof itemKey === 'string' ? itemKey : itemProperties.value;
var elem = new Morebits.quickForm.element({
type: 'option',
label: key + ':' + itemProperties.label,
value: key,
selected: itemProperties.selected,
disabled: (Twinkle.getPref('XfdClose') !== 'all' && itemProperties.adminonly) || itemProperties.disabled,
hidden: itemProperties.hidden
});
var elemRendered = container.appendChild(elem.render());
$(elemRendered).data('messageData', itemProperties);
});
};
Twinkle.close.codes.forEach(function(group) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: group.key
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(group.value, optgroup);
});
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sub_group.dispatchEvent(evt);
};
Twinkle.close.callback.change_operation = function twinklecloseCallbackChangeOperation(e) {
var noop = e.target.checked;
var code = e.target.form.sub_group.value;
var messageData = $(e.target.form.sub_group).find('option[value="' + code + '"]').data('messageData');
var talkpage = e.target.form.talkpage;
var redirects = e.target.form.redirects;
if (noop || messageData.action === 'keep') {
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
if (talkpage) {
talkpage.checked = true;
talkpage.disabled = false;
}
redirects.checked = true;
redirects.disabled = false;
}
};
Twinkle.close.callback.change_code = function twinklecloseCallbackChangeCode(e) {
var resultData = $(e.target.form).data('resultData');
var messageData = $(e.target).find('option[value="' + e.target.value + '"]').data('messageData');
var noop = e.target.form.noop;
var talkpage = e.target.form.talkpage;
var redirects = e.target.form.redirects;
if (resultData.noop || messageData.action === 'noop') {
noop.checked = true;
noop.disabled = true;
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
noop.checked = false;
noop.disabled = false;
if (messageData.action === 'keep') {
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
if (talkpage) {
talkpage.checked = true;
talkpage.disabled = false;
}
redirects.checked = true;
redirects.disabled = false;
}
if (e.target.value === 'sd') {
e.target.form.sdreason.parentElement.removeAttribute('hidden');
} else {
e.target.form.sdreason.parentElement.setAttribute('hidden', '');
}
}
};
Twinkle.close.callback.evaluate = function twinklecloseCallbackEvaluate(e) {
var code = e.target.sub_group.value;
var resultData = $(e.target).data('resultData');
var messageData = $(e.target.sub_group).find('option[value="' + code + '"]').data('messageData');
var noop = e.target.noop.checked;
var talkpage = e.target.talkpage && e.target.talkpage.checked;
var redirects = e.target.redirects.checked;
var params = {
title: resultData.title,
code: code,
remark: e.target.remark.value,
sdreason: e.target.sdreason.value,
section: resultData.section,
parentSection: resultData.parentSection,
messageData: messageData,
talkpage: talkpage,
redirects: redirects
};
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Morebits.wiki.actionCompleted.notice = '操作完成';
if (noop || messageData.action === 'noop') {
Twinkle.close.callbacks.talkend(params);
} else {
switch (messageData.action) {
case 'del':
Twinkle.close.callbacks.del(params);
break;
case 'keep':
var wikipedia_page = new Morebits.wiki.page(params.title, conv({ hans: '移除存废讨论模板', hant: '移除存廢討論模板' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.close.callbacks.keep);
break;
default:
alert('Twinkle.close:未定义 ' + code);
}
}
};
Twinkle.close.callbacks = {
del: function (params) {
var query, wikipedia_api;
Morebits.wiki.addCheckpoint();
var page = new Morebits.wiki.page(params.title, conv({ hans: '删除页面', hant: '刪除頁面' }));
if (params.code === 'sd') {
Twinkle.speedy.callbacks.parseWikitext(params.title, '{{delete|' + params.sdreason + '}}', function(reason) {
reason = prompt(conv({ hans: '输入删除理由,或点击确定以接受自动生成的:', hant: '輸入刪除理由,或點選確定以接受自動生成的:' }), reason);
if (reason === null) {
page.getStatusElement().warn(conv({ hans: '没有执行删除', hant: '沒有執行刪除' }));
Twinkle.close.callbacks.talkend(params);
} else {
page.setEditSummary(reason);
page.setChangeTags(Twinkle.changeTags);
page.deletePage(function() {
page.getStatusElement().info('完成');
Twinkle.close.callbacks.talkend(params);
});
}
});
} else {
page.setEditSummary(conv({ hans: '存废讨论通过:[[', hant: '存廢討論通過:[[' }) + mw.config.get('wgPageName') + '#' + params.title + ']]');
page.setChangeTags(Twinkle.changeTags);
page.deletePage(function() {
page.getStatusElement().info('完成');
Twinkle.close.callbacks.talkend(params);
});
}
if (params.redirects) {
query = {
action: 'query',
titles: params.title,
prop: 'redirects',
rdlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取重定向', hant: '正在取得重新導向' }), query, Twinkle.close.callbacks.deleteRedirectsMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.talkpage) {
var pageTitle = mw.Title.newFromText(params.title);
if (pageTitle && pageTitle.namespace % 2 === 0 && pageTitle.namespace !== 2) {
pageTitle.namespace++; // now pageTitle is the talk page title!
query = {
action: 'query',
titles: pageTitle.toText()
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在检查讨论页面是否存在', hant: '正在檢查討論頁面是否存在' }), query, Twinkle.close.callbacks.deleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = pageTitle.toText();
wikipedia_api.post();
}
}
Morebits.wiki.removeCheckpoint();
},
deleteRedirectsMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('rd').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var redirectDeleter = new Morebits.batchOperation(conv({ hans: '正在删除到 ', hant: '正在刪除到 ' }) + apiobj.params.title + conv({ hans: ' 的重定向', hant: ' 的重新導向' }));
redirectDeleter.setOption('chunkSize', Twinkle.getPref('batchdeleteChunks'));
redirectDeleter.setPageList(pages);
redirectDeleter.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除 ', hant: '正在刪除 ' }) + pageName);
wikipedia_page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '指向已删页面“', hant: '指向已刪頁面「' }) + apiobj.params.title + conv({ hans: '”的重定向', hant: '」的重新導向' }));
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.deletePage(redirectDeleter.workerSuccess, redirectDeleter.workerFailure);
});
},
deleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
if (!exists) {
// no talk page; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + apiobj.params.title + conv({ hans: ' 的讨论页', hant: ' 的討論頁' }));
page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '已删页面“', hant: '已刪頁面「' }) + apiobj.params.title + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.deletePage();
},
keep: function (pageobj) {
var statelem = pageobj.getStatusElement();
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var pagetitle = mw.Title.newFromText(params.title);
if (pagetitle.getNamespaceId() % 2 === 0) {
var talkpagetitle = new mw.Title(pagetitle.getMainText(), pagetitle.getNamespaceId() + 1);
var talkpage = new Morebits.wiki.page(talkpagetitle.toString(), conv({ hans: '标记讨论页', hant: '標記討論頁' }));
var reason = params.messageData.value || params.messageData.label;
var vfdkept = '{{Old vfd multi|' + mw.config.get('wgPageName').split('/').slice(2).join('/') + '|' + reason + '}}\n';
talkpage.setPrependText(vfdkept);
talkpage.setEditSummary('[[' + mw.config.get('wgPageName') + '#' + params.title + ']]:' + reason);
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setCreateOption('recreate');
talkpage.prepend();
}
var newtext = text.replace(/<noinclude>\s*\{\{([rsaiftcmv]fd)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*<\/noinclude>\s*/gi, '');
newtext = newtext.replace(/\{\{([rsaiftcmv]fd)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/gi, '');
if (params.code !== 'tk') {
newtext = newtext.replace(/\{\{(notability|fame|mair|知名度|重要性|显著性|顯著性|知名度不足|人物重要性|重要性不足|notable|关注度|关注度不足|關注度|關注度不足|重要|重要度)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\n*/gi, '');
newtext = newtext.replace(/\{\{(substub|小小作品|cod|小小條目|小小条目)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\n*/gi, '');
}
if (params.code === 'mergeapproved') {
var tag = '{{subst:Merge approved/auto|discuss=' + mw.config.get('wgPageName') + '#' + params.title + '}}\n';
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(newtext);
newtext = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
if (newtext === text) {
statelem.warn(conv({ hans: '未找到存废讨论模板,可能已被移除', hant: '未找到存廢討論模板,可能已被移除' }));
Twinkle.close.callbacks.talkend(params);
return;
}
var editsummary = conv({ hans: '存废讨论关闭:[[', hant: '存廢討論關閉:[[' }) + mw.config.get('wgPageName') + '#' + params.title + ']]';
pageobj.setPageText(newtext);
pageobj.setEditSummary(editsummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.close.callbacks.keepComplete);
},
keepComplete: function (pageobj) {
var params = pageobj.getCallbackParameters();
Twinkle.close.callbacks.talkend(params);
},
talkend: function (params) {
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '关闭讨论', hant: '關閉討論' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setPageSection(params.section);
wikipedia_page.load(Twinkle.close.callbacks.saveTalk);
},
saveTalk: function (pageobj) {
var statelem = pageobj.getStatusElement();
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
if (text.indexOf('{{delh') !== -1) {
statelem.error(conv({ hans: '讨论已被关闭', hant: '討論已被關閉' }));
return;
}
var sbegin = text.indexOf('<section begin=backlog />') !== -1;
var send = text.indexOf('<section end=backlog />') !== -1;
text = text.replace('\n<section begin=backlog />', '');
text = text.replace('\n<section end=backlog />', '');
var bar = text.split('\n----\n');
var split = bar[0].split('\n');
text = split[0] + '\n{{delh|' + params.code + '}}\n';
var reason;
if (params.code === 'relist') {
var dateStr = new Morebits.date().format('YYYY/MM/DD', 'utc');
var logtitle = 'Wikipedia:頁面存廢討論/記錄/' + dateStr;
text += '{{Relisted}}到[[' + logtitle + '#' + params.title + ']]。';
reason = '重新提交到[[' + logtitle + '#' + params.title + '|' + dateStr + ']]';
split[0] = split[0].replace(/^===(.+)===$/, '==$1==');
var relist_params = {
title: params.title,
source: pageobj.getPageName(),
text: split.join('\n'),
comment: params.remark
};
var logpage = new Morebits.wiki.page(logtitle, '重新提交');
if (params.parentSection > 0) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '正在获取批量提删理据…', hant: '正在取得批量提刪理據…' }));
var api = new mw.Api();
api.get({
action: 'query',
format: 'json',
prop: 'revisions',
titles: pageobj.getPageName(),
formatversion: 2,
rvprop: 'content',
rvsection: params.parentSection
}).then(function (data) {
var content = data.query.pages[0].revisions[0].content;
relist_params.batchText = content;
logpage.setCallbackParameters(relist_params);
logpage.load(Twinkle.close.callbacks.relistToday);
});
} else {
logpage.setCallbackParameters(relist_params);
logpage.load(Twinkle.close.callbacks.relistToday);
}
var article_params = {
date: dateStr
};
var articlepage = new Morebits.wiki.page(params.title, conv({ hans: '重新标记', hant: '重新標記' }));
articlepage.setCallbackParameters(article_params);
articlepage.load(Twinkle.close.callbacks.retaggingArticle);
} else {
text += split.slice(1).join('\n');
reason = params.messageData.value || params.messageData.label;
text += '\n<hr>\n: ' + reason;
if (params.remark) {
text += ':' + Morebits.string.appendPunctuation(params.remark);
} else {
text += '。';
}
}
if (!Morebits.userIsSysop) {
text += '{{subst:NAC}}';
}
text += '--~~~~\n{{delf}}';
if (bar[1]) {
text += '\n----\n' + bar.slice(1).join('\n----\n');
}
if (send) {
text += '\n<section end=backlog />';
}
if (sbegin) {
// guaranteed to be at tne end?
text += '\n<section begin=backlog />';
}
pageobj.setPageText(text);
pageobj.setEditSummary('/* ' + params.title + ' */ ' + reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.close.callbacks.disableLink);
},
relistToday: function (pageobj) {
var params = pageobj.getCallbackParameters();
var lines = params.text.replace(/<!-- Twinkle:.+-->\n?/, '').trim().split('\n');
var appendText = '\n{{safesubst:SafeAfdHead}}\n' + lines[0] + '\n';
if (params.batchText) {
var bar = params.batchText.split('\n----\n');
var comment = bar[bar.length - 1];
var m = comment.match(/({{[删刪]除}}理據.*)\n(提[报報]以上.*)/);
if (m) {
appendText += m[1] + '\n: ' + m[2] + '\n';
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法解析批量提删理据', hant: '無法解析批量提刪理據' }));
}
}
appendText += lines.slice(1).join('\n') + '\n{{subst:Relist';
if (params.comment) {
appendText += '|1=' + params.comment;
}
appendText += '}}';
var sourceAnchor = params.source + '#' + params.title;
var dateStr = params.source.replace('Wikipedia:頁面存廢討論/記錄/', '');
pageobj.setAppendText(appendText);
pageobj.setEditSummary('/* ' + params.title + ' */ 重新提交自[[' + sourceAnchor + '|' + dateStr + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
},
retaggingArticle: function (pageobj) {
var statelem = pageobj.getStatusElement();
// defaults to /doc for lua modules, which may not exist
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var params = pageobj.getCallbackParameters();
var text = pageobj.getPageText();
if (/{{[rsaiftcmv]fd\s*(\|.*)?\|\s*date\s*=[^|}]*.*}}/.test(text)) {
text = text.replace(/({{[rsaiftcmv]fd\s*(?:\|.*)?\|\s*date\s*=)[^|}]*(.*}})/, '$1' + params.date + '$2');
} else {
Morebits.status.warn(conv({ hans: '重新标记', hant: '重新標記' }), conv({ hans: '找不到提删模板,重新插入', hant: '找不到提刪模板,重新插入' }));
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
var tag = '{{vfd|date=' + params.date + '}}\n';
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
pageobj.setPageText(text);
pageobj.setEditSummary('重新提交到[[Wikipedia:頁面存廢討論/記錄/' + params.date + '#' + pageobj.getPageName() + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.save();
},
disableLink: function (pageobj) {
var params = pageobj.getCallbackParameters();
$('a.twinkle-close-button[data-section=' + params.section + ']').addClass('twinkle-close-button-disabled');
}
};
Twinkle.addInitCallback(Twinkle.close, 'close');
})(jQuery);
// </nowiki>
8c30fb07a797742217eb55db56605bdc355530a0
Template:Infobox
10
123
240
2024-07-02T03:16:33Z
zhwp>Shizhao
0
自[[Template:Infobox/sandbox]]合并[[Special:Contributions/Dabao qian|Dabao qian]]的[[Special:PermaLink/83243250|版本83243250]]
wikitext
text/x-wiki
<templatestyles src="Module:Infobox/styles.css" />{{#invoke:Infobox|infobox}}<includeonly>{{template other|{{#ifeq:{{PAGENAME}}|Infobox||{{#ifeq:{{str left|{{SUBPAGENAME}}|7}}|Infobox|[[Category:信息框模板|{{remove first word|{{SUBPAGENAME}}}}]]}}|{{#ifeq:{{PAGENAME}}|信息框||{{#ifeq:{{str rightc|{{SUBPAGENAME}}|3}}|信息框|[[Category:信息框模板|{{str crop|{{SUBPAGENAME}}|3}}]]}}|{{#ifeq:{{PAGENAME}}|資訊框||{{#ifeq:{{str rightc|{{SUBPAGENAME}}|3}}|資訊框|[[Category:信息框模板|{{str crop|{{SUBPAGENAME}}|3}}]]}}}}}}}}|}}</includeonly><noinclude>
{{documentation}}
</noinclude>
6f61b0d555bf7e18b6add1c1aae42bae24a5b237
Template:Fake heading/styles.css
10
194
406
2024-07-02T09:33:26Z
zhwp>Shizhao
0
sanitized-css
text/css
.fakeHeading {
overflow: hidden;
page-break-after: avoid;
}
.h1,.h2 {
border-bottom: 1px solid #aaa;
font-family: 'Linux Libertine','Georgia','Times',serif;
font-weight: normal;
line-height: 1.3;
margin-top: 1em;
margin-bottom: 0.25em;
padding: 0;
}
.h1 {
font-size: 1.8em;
}
.h2 {
font-size: 1.5em;
}
.h3,.h4,.h5,.h6 {
font-family: sans-serif;
font-weight: bold;
line-height: 1.6;
margin-top: 0.3em;
margin-bottom: 0;
padding-top: 0.5em;
padding-bottom: 0;
}
.h3 {
font-size: 1.2em;
}
.h4,.h5,.h6 {
font-size: 100%;
}
1171ae88a7b7b14b24abcc01a3fb695d753fafcc
Template:Color
10
316
657
2024-07-04T03:39:47Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<includeonly><span class=skin-invert style="color:{{{1}}};">{{{2}}}</span></includeonly><noinclude>{{doc}}</noinclude>
5b9c964e1a0a2ad063c467d4616047ed6cc08249
Module:CGroup/MediaWiki
828
134
268
2024-07-05T08:22:44Z
zhwp>Kethyga
0
// Edit via Wikiplus
Scribunto
text/plain
-- 用法: Item('原文', '轉換規則')
local Item = require('Module:CGroup/core').Item;
return {
name = 'MediaWiki',
description = 'MediaWiki',
content = {
{ type = 'text', text = [=[
{{NoteTA/MediaWiki}}
本转换组为MediaWiki及中文维基百科专有用语。
由于中文维基百科部分统一用语与常见IT术语不同,可视情况与[[Module:CGroup/IT]]配合使用来抵消[[Module:CGroup/IT]]带来的过度转换。
本转换组只应用于Wikipedia、Help、Template等命名空间或与维基百科相关的条目,请勿用于其他主命名空间条目内。
如無特別需求請直接使用{{tlx|NoteTA/MediaWiki}}
== 專有名稱 ==
]=] },
Item('account', 'zh-cn:账号; zh-tw:帳號;'),
Item('account', '账户=>zh-cn:账号; 账户=>zh-tw:帳號;'),
Item('account', '賬戶=>zh-cn:账号; 賬戶=>zh-tw:帳號;'),
Item('account', '賬號=>zh-cn:账号; 賬號=>zh-tw:帳號;'),
Item('account', '帐户=>zh-cn:账号; 帐户=>zh-tw:帳號;'),
Item('account', '帳戶=>zh-cn:账号;'),
Item('account', '帐号=>zh-cn:账号; 帐号=>zh-tw:帳號;'),
Item('account creator', 'zh-cn:大量账号创建者; zh-tw:大量帳號建立者; zh-hk:大量帳號建立者;'),
Item('advanced', 'zh-cn:高级; zh-tw:進階;'),
Item('authority control', 'zh-cn:规范控制; zh-tw:權威控制;'),
Item('block', 'zh-cn:封禁; zh-tw:封鎖; zh-hk:封鎖;'),
Item('change', 'zh-cn:更改; zh-tw:變更;'),
Item('character', 'zh-cn:字符; zh-tw:字元;'),
Item('copyright', 'zh-cn:著作权; zh-tw:著作權; zh-hk:版權; zh-mo:著作權;'),
Item('copyright', '版权=>zh-tw:著作權; 版权=>zh-mo:著作權;'),
Item('copyright information', '版权信息=>zh-cn:著作权信息; 版权信息=>zh-sg:著作权信息; 版权信息=>zh-my:著作权信息; 版权信息=>zh-tw:著作權資訊; 版权信息=>zh-mo:著作權資訊;'),
Item('create', 'zh-cn:创建; zh-tw:建立;'),
Item('create', '創建=>zh-tw:建立; 創建=>zh-hk:建立; 創建=>zh-mo:建立;'),
Item('custom', 'zh-cn:自定义; zh-tw:自訂;'),
Item('custom', '自定義=>zh-hk:自訂; 自定義=>zh-tw:自訂;'),
Item('custom', '自定=>zh-hk:自訂; 自定=>zh-tw:自訂;'),
Item('default', 'zh-cn:默认; zh-tw:預設;'),
Item('default', '默認=>zh-tw:預設;'),
Item('file', 'zh-cn:文件; zh-tw:檔案;'),
Item('file', '档案=>zh-cn:文件; 档案=>zh-sg:文件; 档案=>zh-my:文件;'),
Item('file name', 'zh-cn:文件名; zh-tw:檔案名稱;'),
Item('flood', 'zh-hans:机器用户; zh-tw:機器使用者; zh-hk:機械用戶;'),
Item('footnote', 'zh-cn:脚注; zh-tw:註腳;'),
Item('Help:', 'zh-cn:帮助:; zh-tw:說明:;'),
Item('Help talk:', 'zh-cn:帮助讨论:; zh-tw:說明討論:;'),
Item('info (information)', 'zh-cn:信息; zh-tw:資訊;'),
Item('interface', 'zh-hans:界面; zh-hant:介面;'),
Item('interface administrators', 'zh-cn:界面管理员; zh-tw:介面管理員;'),
Item('IP block exemption', 'zh-cn:IP封禁豁免; zh-tw:IP封鎖豁免;'),
Item('IP block exemption', 'IP封禁例外=>zh-hans:IP封禁豁免; IP封禁例外=>zh-hant:IP封鎖豁免;'),
Item('IP block exemption', 'IP封鎖例外=>zh-hans:IP封禁豁免; IP封禁例外=>zh-hant:IP封鎖豁免;'),
--[=[
抄自[[Module:CGroup/IT]]
因為現在要求不要沒事加上IT以防過度轉換
結果 链接/鏈接/連結 又不轉換了
]=]
Item('import', 'zh-cn:导入; zh-tw:匯入;'),
Item('import', '汇入=>zh-cn:导入; 汇入=>zh-sg:导入; 汇入=>zh-my:导入;'),
Item('import', '導入=>zh-tw:匯入; 導入=>zh-hk:匯入; 導入=>zh-mo:匯入;'),
Item('line breaker', 'zh-hans:换行符;zh-hant:換行字元;'),
Item('line breaker', 'zh:換行符;zh-hans:换行符;zh-hant:換行字元;'),
Item('line breaker', 'zh:换行字元;zh-hans:换行符;zh-hant:換行字元;'),
Item('link', 'zh-cn:链接; zh-tw:連結;'),
Item('link', '连结=>zh-cn:链接; 连结=>zh-sg:链接; 连结=>zh-my:链接;'),
Item('link', '鏈接=>zh-tw:連結; 鏈接=>zh-hk:連結; 鏈接=>zh-mo:連結;'),
Item('link', '鏈結=>zh-tw:連結; 鏈結=>zh-hk:連結; 鏈結=>zh-mo:連結;'),
Item('internal link', '内链=>zh-tw:內部連結; 内链=>zh-hk:內部連結; 内链=>zh-mo:內部連結;'),
Item('internal link', '內鏈=>zh-tw:內部連結; 內鏈=>zh-hk:內部連結; 內鏈=>zh-mo:內部連結;'),
Item('external link', '外链=>zh-tw:外部連結; 外链=>zh-hk:外部連結; 外链=>zh-mo:外部連結;'),
Item('external link', '外鏈=>zh-tw:外部連結; 外鏈=>zh-hk:外部連結; 外鏈=>zh-mo:外部連結;'),
Item('red link', '红链=>zh-tw:紅色連結; 红链=>zh-hk:紅色連結; 红链=>zh-mo:紅色連結;'),
Item('red link', '紅鏈=>zh-tw:紅色連結; 紅鏈=>zh-hk:紅色連結; 紅鏈=>zh-mo:紅色連結;'),
Item('green link', '绿链=>zh-tw:綠色連結; 绿链=>zh-hk:綠色連結; 绿链=>zh-mo:綠色連結;'),
Item('green link', '綠鏈=>zh-tw:綠色連結; 綠鏈=>zh-hk:綠色連結; 綠鏈=>zh-mo:綠色連結;'),
Item('blue link', '蓝链=>zh-tw:藍色連結; 蓝链=>zh-hk:藍色連結; 蓝链=>zh-mo:藍色連結;'),
Item('blue link', '藍鏈=>zh-tw:藍色連結; 藍鏈=>zh-hk:藍色連結; 藍鏈=>zh-mo:藍色連結;'),
Item('link (here)', 'zh-cn:链入; zh-tw:連入;'),
Item('link (here)', '鏈入=>zh-tw:連入;'),
-- end
Item('log details', 'zh-hans:日志详情; zh-hant:日誌明細;'),
Item('login', 'zh-hans:登录; zh-hant:登入;'),
Item('logout', 'zh-hant:登出; zh-hans:退出;'), -- 覆蓋[[Module_talk:CGroup/IT#編輯請求_2023-06-13]]
Item('logout', '退出登录 => zh-tw:登出; 退出登录 => zh-hk:登出; 退出登录 => zh-mo:登出; '), -- 你永遠想不到編者怎麼造成轉換錯誤
Item('module', 'zh-cn:模块; zh-tw:模組;'),
Item('module', '模组=>zh-cn:模块; 模组=>zh-sg:模块; 模组=>zh-my:模块;'),
Item('namespace', 'zh-hans:命名空间; zh-hant:命名空間;'),
Item('namespace', '名字空间=>zh-cn:命名空间; 名字空间=>zh-hk:命名空間; 名字空间=>zh-mo:命名空間; 名字空间=>zh-tw:命名空間; 名字空间=>zh-sg:命名空间; 名字空间=>zh-my:命名空间;'),
Item('namespace', '名字空間=>zh-cn:命名空间; 名字空間=>zh-hk:命名空間; 名字空間=>zh-mo:命名空間; 名字空間=>zh-tw:命名空間; 名字空間=>zh-sg:命名空间; 名字空間=>zh-my:命名空间;'),
Item('parser functions', 'zh-cn:解析器函数; zh-hk:解析器函數; zh-tw:解析器函數;'),
Item('preferences', 'zh-cn:参数设置; zh-tw:偏好設定; zh-hk:參數設置;'),
Item('project', 'zh-hans:项目; zh-hant:專案; zh-tw:專案;'),
--[=[
誤轉率過高,真的要用請用 项目 代替 項目 即可轉換
Item('project', '項目=>zh-tw:專案; 項目=>zh-hk:專案; 項目=>zh-mo:專案;'),
]=]--
Item('project', '专案=>zh-cn:项目; 专案=>zh-sg:项目; 专案=>zh-my:项目; 专案=>zh-tw:專案;'),
Item('project', '計劃=>zh-cn:项目; 計劃=>zh-sg:项目; 計劃=>zh-my:项目; 計劃=>zh-tw:專案; 計劃=>zh-hk:專案; 計劃=>zh-mo:專案;'),
Item('project page', 'zh-hans:项目页面; zh-hant:專案頁面; zh-tw:專案頁面;'),
Item('project page', '項目頁面=>zh-tw:計畫頁面; 項目頁面=>zh-hk:專案頁面; 項目=>zh-mo:專案頁面;'),
Item('recent change', 'zh-hans:最近更改; zh-hant:近期變更;'),
Item('redirect', 'zh-cn:重定向; zh-tw:重新導向;'),
Item('redirect page', 'zh-cn:重定向页; zh-tw:重新導向頁面;'),
Item('redirect page', '重定向页面=>zh-tw:重新導向頁面; 重定向页面=>zh-hk:重新導向頁面; 重定向页面=>zh-mo:重新導向頁面;'),
Item('report', 'zh-cn:举报; zh-tw:檢舉;'),
Item('sample', 'zh-cn:示例; zh-tw:範例;'),
Item('skin', '皮肤=>zh-tw:外觀; 皮肤=>zh-hk:外觀; 皮肤=>zh-mo:外觀;'),
Item('source code', 'zh-hans:原始码; zh-hant:原始碼; zh-cn:源代码;'),
Item('source code', '源代碼=>zh-hk:原始碼; 源代碼=>zh-mo:原始碼; 源代碼=>zh-tw:原始碼; 源代碼=>zh-sg:原始码; 源代碼=>zh-my:原始码;'),
Item('source code', '源码=>zh-hk:原始碼; 源码=>zh-mo:原始碼; 源码=>zh-tw:原始碼; 源码=>zh-sg:原始码; 源码=>zh-my:原始码;'),
Item('source code', '源碼=>zh-hk:原始碼; 源碼=>zh-mo:原始碼; 源碼=>zh-tw:原始碼; 源碼=>zh-sg:原始码; 源碼=>zh-my:原始码;'),
Item('string', 'zh-cn:字符串; zh-tw:字串;'),
Item('template data', 'zh-hans:模板数据; zh-hant:模板資料; zh-tw:模板資料;'),
Item('template documentation', 'zh-hans:模板文档; zh-hant:模板文件;'),
Item('through', 'zh-cn:通过; zh-tw:透過;'),
Item('undo', 'zh-cn:撤销; zh-tw:復原;'),
Item('undo', '撤消=>zh-tw:復原; 撤消=>zh-hk:復原; 撤消=>zh-mo:復原;'),
Item('user', 'zh-hans:用户; zh-hant:使用者; zh-tw:使用者; zh-hk:用戶;'), ---容易过度转换
Item('user group', 'zh-cn:用户组; zh-tw:使用者群組; zh-hk:用戶組;'),
Item('user page', 'zh-cn:用户页; zh-tw:使用者頁面; zh-hk:用戶頁;'),
Item('user page', '用户頁=>zh-tw:使用者頁面;'),
Item('user page', '用戶页=>zh-tw:使用者頁面;'),
Item('user page', '用户页面=>zh-tw:使用者頁面;'),
Item('user page', '使用者頁=>zh-tw:使用者頁面;'),
Item('user page', '使用者頁面=>zh-tw:使用者頁面;'),
Item('user right', '用户权限 => zh-tw:使用者權限;用戶權限 => zh-tw:使用者權限;'),
Item('user right', '用户权 => zh-tw:使用者權限;用戶權 => zh-tw:使用者權限;'),
Item('userbox', 'zh-cn:用户框; zh-tw:使用者方塊; zh-hk:用戶框;'),
Item('username', 'zh-hans:用户名; zh-hant:用戶名; zh-tw:使用者名稱;'),
Item('username', '用户名称=>zh-cn:用户名; 用户名称=>zh-my:用户名; 用户名称=>zh-sg:用户名; 用户名称=>zh-tw:使用者名稱;'),
Item('username', '用戶名稱=>zh-cn:用户名; 用戶名稱=>zh-my:用户名; 用戶名稱=>zh-sg:用户名; 用戶名稱=>zh-tw:使用者名稱;'),
Item('view', 'zh-cn:查看; zh-tw:檢視;'),
Item('visual', 'zh-cn:可视化; zh-tw:視覺化;'), -- VisualEditor
Item('watchlist', 'zh-cn:监视列表; zh-tw:監視清單;'),
{ type = 'text', text = [=[
== 避免過度轉換 ==
]=] },
--[=[
此區僅用來防止過度轉換,請按照過度轉換源提供的轉換方式(ex.zh-hans:xxx; zh-hant:xxx; 或 zh-cn:xxx; zh-tw:xxx;)加入,避免無法覆蓋
]=]--
Item('archives', 'zh-cn:档案馆; zh-tw:檔案館;'), -- 避免 档案馆->文件馆 的過度轉換
Item('archives', '档案馆=>zh-cn:档案馆; 档案馆=>zh-sg:档案馆; 档案馆=>zh-my:档案馆;'), -- 避免 档案馆->文件馆 的過度轉換
Item('administrator intervention against vandalism', 'zh-hans:当前的破坏; zh-hant:目前的破壞;'), -- 「当前=>目前」非過度轉換
Item('cite', 'zh-hans:引用; zh-hant:引用;'), -- 避免 引用->參照 的過度轉換
Item('commons', 'zh-hans:共享资源; zh-hant:共享資源;'), -- 避免 共享->共用 的過度轉換
Item('global', 'zh-cn:全域; zh-tw:全域;'),
Item('log', 'zh-hans:日志; zh-hant:日誌;'), -- 避免 日志->紀錄檔 的過度轉換
Item('log entry', 'zh-cn:日志项目; zh-tw:日誌項目;'), -- 避免 项目->專案/計畫/計劃 的過度轉換
Item(nil, 'zh-hans:主页面; zh-hant:主頁面;'), -- 避免 主頁->首頁 的過度轉換
Item('message', 'zh-hans:讯息; zh-hant:訊息;'), -- 避免 訊息->消息 的過度轉換
Item('native', 'zh-hans:本地的; zh-hant:本地的;'), -- 避免 本地的->原生的 的過度轉換
Item('object', 'zh-hans:对象; zh-hant:對象;'), -- 避免 对象->物件 的過度轉換
Item('perform', 'zh-hans:执行; zh-hant:執行;'), -- 避免 執行->运行 的過度轉換
Item('procedure', 'zh-hans:程序; zh-hant:程序;'), -- 避免 程序->程式 的過度轉換
Item('segment', 'zh-hans:区段; zh-hant:區段;'), -- 避免 區段->区块 的過度轉換
Item('sign', 'zh-hans:签名; zh-hant:簽名;'), -- 避免 签名->簽章 的過度轉換
Item('support', 'zh-hans:支持; zh-hant:支持;'), -- 避免 支持->支援 的過度轉換
Item('user namespace', '用户名字空間=>zh-hk:用戶命名空間; 用户名字空間=>zh-mo:用戶命名空間; 用户名字空間=>zh-tw:使用者命名空間;'), -- 避免 用户名->使用者名稱 的過度轉換
Item('user namespace', '用戶名字空间=>zh-hk:用戶命名空間; 用戶名字空间=>zh-mo:用戶命名空間; 用戶名字空间=>zh-tw:使用者命名空間;'), -- 避免 用戶名->使用者名稱 的過度轉換
Item('user namespace', '用戶名字空間=>zh-hk:用戶命名空間; 用戶名字空間=>zh-mo:用戶命名空間; 用戶名字空間=>zh-tw:使用者命名空間;'), -- 避免 用戶名->使用者名稱 的過度轉換
-- 註:“名字空間”是舊的簡體中文譯名,後來簡體中文譯名改為“命名空間”,與繁體用詞保持一致。參見[[维基百科:互助客栈/其他/存档/2021年10月#關於zh-hans/zh-Hans-CN中namespace的翻譯]]。舊的用法保留在轉換表中。
Item('community', 'zh-hans:社群; zh-hant:社群;'), -- 避免 社区->社群 的過度轉換
Item(nil, '授權=>zh-cn:授权; zh-tw:授權;'), -- 避免 授權->特許 的過度轉換
Item(nil, '特許=>zh-cn:授权; zh-tw:特許;'), -- 避免 授權->特許 的過度轉換
},
}
544bbe041f7983229cdd1111fe31a6be6b0bf162
Module:Tlg
828
235
489
2024-07-08T12:05:35Z
zhwp>Shizhao
0
Scribunto
text/plain
-- This implements Template:Tlg
local getArgs = require('Module:Arguments').getArgs
local p = {}
-- Is a string non-empty?
local function _ne(s)
return s ~= nil and s ~= ""
end
local nw = mw.text.nowiki
local function addTemplate(s)
local i, _ = s:find(':', 1, true)
if i == nil then
return 'Template:' .. s
end
local ns = s:sub(1, i - 1)
if ns == '' or mw.site.namespaces[ns] then
return s
else
return 'Template:' .. s
end
end
local function trimTemplate(s)
local needle = 'template:'
if s:sub(1, needle:len()):lower() == needle then
return s:sub(needle:len() + 1)
else
return s
end
end
local function linkTitle(args)
if _ne(args.nolink) then
return args['1']
end
local titleObj
local titlePart = '[['
if args['1'] then
-- This handles :Page and other NS
titleObj = mw.title.new(args['1'], 'Template')
else
titleObj = mw.title.getCurrentTitle()
end
titlePart = titlePart .. (titleObj ~= nil and titleObj.fullText or
addTemplate(args['1']))
local textPart = args.alttext
if not _ne(textPart) then
if titleObj ~= nil then
textPart = titleObj:inNamespace("Template") and args['1'] or titleObj.fullText
else
-- redlink
textPart = args['1']
end
end
if _ne(args.subst) then
-- HACK: the ns thing above is probably broken
textPart = 'subst:' .. textPart
end
if _ne(args.brace) then
textPart = nw('{{') .. textPart .. nw('}}')
elseif _ne(args.braceinside) then
textPart = nw('{') .. textPart .. nw('}')
end
titlePart = titlePart .. '|' .. textPart .. ']]'
if _ne(args.braceinside) then
titlePart = nw('{') .. titlePart .. nw('}')
end
return titlePart
end
function p.main(frame)
local args = getArgs(frame, {
trim = true,
removeBlanks = false
})
return p._main(args)
end
function p._main(args)
local bold = _ne(args.bold) or _ne(args.boldlink) or _ne(args.boldname)
local italic = _ne(args.italic) or _ne(args.italics)
local dontBrace = _ne(args.brace) or _ne(args.braceinside)
local code = _ne(args.code) or _ne(args.tt)
local show_result = _ne(args._show_result)
local expand = _ne(args._expand)
-- Build the link part
local titlePart = linkTitle(args)
if bold then titlePart = "'''" .. titlePart .. "'''" end
if _ne(args.nowrapname) then titlePart = '<span class="nowrap">' .. titlePart .. '</span>' end
-- Build the arguments
local textPart = ""
local textPartBuffer = "|"
local codeArguments = {}
local codeArgumentsString = ""
local i = 2
local j = 1
while args[i] do
local val = args[i]
if val ~= "" then
if _ne(args.nowiki) then
-- Unstrip nowiki tags first because calling nw on something that already contains nowiki tags will
-- mangle the nowiki strip marker and result in literal UNIQ...QINU showing up
val = nw(mw.text.unstripNoWiki(val))
end
local k, v = string.match(val, "(.*)=(.*)")
if not k then
codeArguments[j] = val
j = j + 1
else
codeArguments[k] = v
end
codeArgumentsString = codeArgumentsString .. textPartBuffer .. val
if italic then
val = '<span style="font-style:italic;">' .. val .. '</span>'
end
textPart = textPart .. textPartBuffer .. val
end
i = i + 1
end
-- final wrap
local ret = titlePart .. textPart
if not dontBrace then ret = nw('{{') .. ret .. nw('}}') end
if _ne(args.a) then ret = nw('*') .. ' ' .. ret end
if _ne(args.kbd) then ret = '<kbd>' .. ret .. '</kbd>' end
if code then
ret = '<code>' .. ret .. '</code>'
elseif _ne(args.plaincode) then
ret = '<code style="border:none;">' .. ret .. '</code>'
end
if _ne(args.nowrap) then ret = '<span class="nowrap">' .. ret .. '</span>' end
--[[ Wrap as html??
local span = mw.html.create('span')
span:wikitext(ret)
--]]
if _ne(args.debug) then ret = ret .. '\n<pre>' .. mw.text.encode(mw.dumpObject(args)) .. '</pre>' end
if show_result then
local result = mw.getCurrentFrame():expandTemplate{title = addTemplate(args[1]), args = codeArguments}
ret = ret .. " → " .. result
end
if expand then
local query = mw.text.encode('{{' .. addTemplate(args[1]) .. string.gsub(codeArgumentsString, textPartBuffer, "|") .. '}}')
local url = mw.uri.fullUrl('special:ExpandTemplates', 'wpInput=' .. query)
mw.log()
ret = ret .. " [" .. tostring(url) .. "]"
end
return ret
end
return p
2be73a9f60f9b5e8d38cbfcd220d2670c021f247
那艺娜维基:Sandbox heading
4
22
39
2024-07-10T12:47:10Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<!--
简体中文
注意:这不是一个沙盒!!!
这是一个放置于沙盒顶端的模板。
如果你想练习编辑,请不要在这个模板上进行。
你可以通过在搜索中输入“WP:S”或“WP:Temp”或“WP:SB”或“Wikipedia:沙盒”找到真正的沙盒
如果你想在模板空间测试,请前往 “Template:沙盒” 或 “Template:X1” 和 “Template:X2”
再次申明,这个模版不是用于试验的!
这个沙盒模版位于:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><!--
繁體中文
注意:這不是一個沙盒!!!
這是一個放置於沙盒頂端的模板。
如果你想練習編輯,請不要在這個模板上進行。
你可以透過在搜尋中輸入「WP:Temp」或「WP:SB」或「Wikipedia:沙盒」找到真正的沙盒
如果你想在模板空間測試,請前往「WP:S」或「Template:沙盒」或「Template:X1」和「Template:X2」
再次申明,這個模板不是用於試驗的!
這個沙盒模板位於:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><noinclude>{{About|置于沙盒顶端的提示-{zh-hant:資訊; zh-hans:信息;}-。'''本模板本身不是沙盒'''|用于测试的模板沙盒|模板:沙盒}}{{nottest}}</noinclude><includeonly>__NOINDEX__</includeonly>
{{noEdit}}
<!-- 不应修改沙盒的首段 - 首段包含对此模板的引用 -->
<div class="messagebox plainlinks" style="padding: 10px; margin: 20px auto; width: 100%; font-size: 10pt;background-color:var(--background-color-interactive-subtle,#f8f9fa);color: inherit;">
{|
|-
||[[File:Edit_In_Sandbox_Icon_-_Color.svg|75px|left|alt=|link=]]
||<big>欢迎来到'''[[Wikipedia:关于沙盒|维基百科沙盒]]'''!</big>
{{{editnotice|
如果{{lan|zh-hans=您|zh-hant=您|zh-hk=閣下}}想要在此測試,請{{Fullurl|1={{FULLPAGENAME}}|2=action=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}或上方的{{If mobile|'''鉛筆{{lan|zh-hans=图标|zh-hant=圖示}}'''|{{#if:{{{1|}}}||'''編輯{{lan|zh-cn=源代码|zh-sg=原始码|zh-tw=原始碼}}'''}}}}即可,也可{{Fullurl|1={{FULLPAGENAME}}|2=veaction=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}使用[[WP:VE|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]]進行編輯。}}}
沙盒是用于练习页面编辑技巧的測試页面。您可在此随意地进行编辑的练习。完成编辑后,可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Showpreview}}'''”按钮预览内容,也可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Publishchanges}}'''”按钮{{lan|zh-cn=保存|zh-tw=儲存}}内容。就像在沙灘上所寫的文字涨潮时就會消失,同样沙盒中所寫的內容,隨時可能被清空,不會有任何預先通知(但曾{{lan|zh-cn=保存|zh-tw=儲存}}的内容仍会永久存留在页面的历史记录中)。
||
{{#switch: {{FULLPAGENAME}}
| Wikipedia:沙盒 = {{Shortcut|WP:S|WP:SB|WP:SAND|WP:TMP|WP:TEST|WP:FOO}}<!--
| Template:沙盒 = {{Shortcut|T:SB}} -->
| Template:X1 = {{Shortcut|T:X1}}
| Template:X2 = {{Shortcut|T:X2}}
| Template:X3 = {{Shortcut|T:X3}}
| Category:沙盒 = {{Shortcut|CAT:SB}}
| 模块:沙盒 = {{Shortcut|Module:SB}}
| Draft:沙盒 = {{Shortcut|Draft:SB}}
| Template:沙盒/test.css = {{Shortcut|T:SB/CSS}}
}}
|}
{{columns|bgcol=transparent;width:100%|width=50%
|col1 = '''注意事项''':
* '''不要'''在公用的沙盒撰写条目或存放其他有价值的内容(請参考[[Help:创建新条目|{{lan|zh-cn=创建|zh-tw=建立}}新页面]]及[[WP:WIZ|{{lan|zh-cn=创建|zh-tw=建立}}条目向导]]);
* '''不要'''在沙盒{{lan|zh-cn=里|zh-hk=裏|zh-tw=裡}}{{lan|zh-cn=保存|zh-tw=儲存}}有侵犯他人版权、攻击性、诽谤中伤他人或他人隱私的内容;
* '''不要'''将沙盒[[Wikipedia:重定向|{{lan|zh-cn=重定向|zh-tw=重新導向}}]]至别的页面,或将顶部模板移除;
* '''不要'''在沙盒進行廣告宣傳或刷编辑次数,否則可能會被[[Wikipedia:封禁方针|{{lan|zh-hans=封禁|zh-hant=封鎖}}]];
* 歡迎參考[[Wikipedia:常见问题解答|常見問題解答]]及[[Wikipedia:新手入門/主頁|使用指南]];
* 如果对[[维基百科]]有任何问题,請到[[Wikipedia:互助客栈|互助客栈]]询问。
|col2 = '''工具''':
{{div col|cols=2}}
* [[Wikipedia:沙盒|主沙盒]]
** {{fullurl2|Wikipedia:沙盒|action=edit|原始碼編輯}}
** {{fullurl2|Wikipedia:沙盒|veaction=edit|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯}}
* {{noredirect|Wikipedia:重定向沙盒|{{lan|zh-cn=重定向|zh-tw=重新導向}}沙盒}}
* [[User:沙盒页|{{lan|zh-cn=用户页|zh-tw=使用者頁面}}沙盒]]
* [[Template:沙盒|模板測試沙盒]]([[Template:X1|X1]]、[[Template:X2|X2]]、[[Template:X3|X3]]、[[Template:沙盒/TemplateStyles|TS]])
* [[Template:沙盒/TemplateStyles|模板樣式總測試沙盒]]
* [[:Category:沙盒|分類測試沙盒]]
* 圖片測試沙盒:[[:File:沙盒.png|PNG]]、[[:File:沙盒.svg|SVG]]
* [[User talk:Sandbox for user warnings~zhwiki|对话页測試沙盒]]([[User talk:Sandbox for user warnings~zhwiki~Flow|Flow版]])
* [[Module:沙盒|{{lan|zh-hans=模块|zh-hant=模組}}總測試沙盒]]
* [[Wikipedia talk:Flow tests|Flow對話沙盒]]
* [{{fullurl:Draft:沙盒|veaction=edit}} {{lan|zh-hans=可视化|zh-hant=視覺化}}编辑器沙盒]
* [[WP:Huggle/Sandbox|Huggle沙盒]]
* [[Special:ApiSandbox|API沙盒]]
* 維基數據沙盒:[[:d:Q4115189|1]]、[[:d:Q13406268|2]]、[[:d:Q15397819|3]]、[[:d:Q112795079|4]]
* [[testwiki:|測試維基]]
* [[mw:Project:Sandbox|MediaWiki沙盒]]([[mw:VisualEditor:Test|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]])
* [{{fullurl:Special:Mypage/沙盒|action=edit&preload=Template:用戶沙盒/preload}} 您自己的沙盒]
* [[Wikipedia:關於沙盒|其他{{lan|zh-hans=资料|zh-hant=資料}}]]
{{div col end}}
}}
</div><div class="abusefilter-sandbox-header"></div><includeonly>
{{#switch:{{FULLPAGENAME}}
| Category:沙盒 = {{hiddencat}}
[[Category:維基百科管理]]
| #default = {{#ifeq:{{NAMESPACE}}|User||{{#ifeq:{{NAMESPACE}}|User talk||{{#if:{{{8|}}}||[[Category:沙盒]]}}}}}}
}}</includeonly>
{{{editnotice|
----}}}<noinclude>
{{doc}}
</noinclude>
f2ad992b81199261b0c806fb320939944a642b1a
Template:Sandbox heading
10
50
93
2024-07-10T12:47:10Z
zhwp>Shizhao
0
wikitext
text/x-wiki
<!--
简体中文
注意:这不是一个沙盒!!!
这是一个放置于沙盒顶端的模板。
如果你想练习编辑,请不要在这个模板上进行。
你可以通过在搜索中输入“WP:S”或“WP:Temp”或“WP:SB”或“Wikipedia:沙盒”找到真正的沙盒
如果你想在模板空间测试,请前往 “Template:沙盒” 或 “Template:X1” 和 “Template:X2”
再次申明,这个模版不是用于试验的!
这个沙盒模版位于:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><!--
繁體中文
注意:這不是一個沙盒!!!
這是一個放置於沙盒頂端的模板。
如果你想練習編輯,請不要在這個模板上進行。
你可以透過在搜尋中輸入「WP:Temp」或「WP:SB」或「Wikipedia:沙盒」找到真正的沙盒
如果你想在模板空間測試,請前往「WP:S」或「Template:沙盒」或「Template:X1」和「Template:X2」
再次申明,這個模板不是用於試驗的!
這個沙盒模板位於:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><noinclude>{{About|置于沙盒顶端的提示-{zh-hant:資訊; zh-hans:信息;}-。'''本模板本身不是沙盒'''|用于测试的模板沙盒|模板:沙盒}}{{nottest}}</noinclude><includeonly>__NOINDEX__</includeonly>
{{noEdit}}
<!-- 不应修改沙盒的首段 - 首段包含对此模板的引用 -->
<div class="messagebox plainlinks" style="padding: 10px; margin: 20px auto; width: 100%; font-size: 10pt;background-color:var(--background-color-interactive-subtle,#f8f9fa);color: inherit;">
{|
|-
||[[File:Edit_In_Sandbox_Icon_-_Color.svg|75px|left|alt=|link=]]
||<big>欢迎来到'''[[Wikipedia:关于沙盒|维基百科沙盒]]'''!</big>
{{{editnotice|
如果{{lan|zh-hans=您|zh-hant=您|zh-hk=閣下}}想要在此測試,請{{Fullurl|1={{FULLPAGENAME}}|2=action=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}或上方的{{If mobile|'''鉛筆{{lan|zh-hans=图标|zh-hant=圖示}}'''|{{#if:{{{1|}}}||'''編輯{{lan|zh-cn=源代码|zh-sg=原始码|zh-tw=原始碼}}'''}}}}即可,也可{{Fullurl|1={{FULLPAGENAME}}|2=veaction=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}使用[[WP:VE|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]]進行編輯。}}}
沙盒是用于练习页面编辑技巧的測試页面。您可在此随意地进行编辑的练习。完成编辑后,可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Showpreview}}'''”按钮预览内容,也可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Publishchanges}}'''”按钮{{lan|zh-cn=保存|zh-tw=儲存}}内容。就像在沙灘上所寫的文字涨潮时就會消失,同样沙盒中所寫的內容,隨時可能被清空,不會有任何預先通知(但曾{{lan|zh-cn=保存|zh-tw=儲存}}的内容仍会永久存留在页面的历史记录中)。
||
{{#switch: {{FULLPAGENAME}}
| Wikipedia:沙盒 = {{Shortcut|WP:S|WP:SB|WP:SAND|WP:TMP|WP:TEST|WP:FOO}}<!--
| Template:沙盒 = {{Shortcut|T:SB}} -->
| Template:X1 = {{Shortcut|T:X1}}
| Template:X2 = {{Shortcut|T:X2}}
| Template:X3 = {{Shortcut|T:X3}}
| Category:沙盒 = {{Shortcut|CAT:SB}}
| 模块:沙盒 = {{Shortcut|Module:SB}}
| Draft:沙盒 = {{Shortcut|Draft:SB}}
| Template:沙盒/test.css = {{Shortcut|T:SB/CSS}}
}}
|}
{{columns|bgcol=transparent;width:100%|width=50%
|col1 = '''注意事项''':
* '''不要'''在公用的沙盒撰写条目或存放其他有价值的内容(請参考[[Help:创建新条目|{{lan|zh-cn=创建|zh-tw=建立}}新页面]]及[[WP:WIZ|{{lan|zh-cn=创建|zh-tw=建立}}条目向导]]);
* '''不要'''在沙盒{{lan|zh-cn=里|zh-hk=裏|zh-tw=裡}}{{lan|zh-cn=保存|zh-tw=儲存}}有侵犯他人版权、攻击性、诽谤中伤他人或他人隱私的内容;
* '''不要'''将沙盒[[Wikipedia:重定向|{{lan|zh-cn=重定向|zh-tw=重新導向}}]]至别的页面,或将顶部模板移除;
* '''不要'''在沙盒進行廣告宣傳或刷编辑次数,否則可能會被[[Wikipedia:封禁方针|{{lan|zh-hans=封禁|zh-hant=封鎖}}]];
* 歡迎參考[[Wikipedia:常见问题解答|常見問題解答]]及[[Wikipedia:新手入門/主頁|使用指南]];
* 如果对[[维基百科]]有任何问题,請到[[Wikipedia:互助客栈|互助客栈]]询问。
|col2 = '''工具''':
{{div col|cols=2}}
* [[Wikipedia:沙盒|主沙盒]]
** {{fullurl2|Wikipedia:沙盒|action=edit|原始碼編輯}}
** {{fullurl2|Wikipedia:沙盒|veaction=edit|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯}}
* {{noredirect|Wikipedia:重定向沙盒|{{lan|zh-cn=重定向|zh-tw=重新導向}}沙盒}}
* [[User:沙盒页|{{lan|zh-cn=用户页|zh-tw=使用者頁面}}沙盒]]
* [[Template:沙盒|模板測試沙盒]]([[Template:X1|X1]]、[[Template:X2|X2]]、[[Template:X3|X3]]、[[Template:沙盒/TemplateStyles|TS]])
* [[Template:沙盒/TemplateStyles|模板樣式總測試沙盒]]
* [[:Category:沙盒|分類測試沙盒]]
* 圖片測試沙盒:[[:File:沙盒.png|PNG]]、[[:File:沙盒.svg|SVG]]
* [[User talk:Sandbox for user warnings~zhwiki|对话页測試沙盒]]([[User talk:Sandbox for user warnings~zhwiki~Flow|Flow版]])
* [[Module:沙盒|{{lan|zh-hans=模块|zh-hant=模組}}總測試沙盒]]
* [[Wikipedia talk:Flow tests|Flow對話沙盒]]
* [{{fullurl:Draft:沙盒|veaction=edit}} {{lan|zh-hans=可视化|zh-hant=視覺化}}编辑器沙盒]
* [[WP:Huggle/Sandbox|Huggle沙盒]]
* [[Special:ApiSandbox|API沙盒]]
* 維基數據沙盒:[[:d:Q4115189|1]]、[[:d:Q13406268|2]]、[[:d:Q15397819|3]]、[[:d:Q112795079|4]]
* [[testwiki:|測試維基]]
* [[mw:Project:Sandbox|MediaWiki沙盒]]([[mw:VisualEditor:Test|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]])
* [{{fullurl:Special:Mypage/沙盒|action=edit&preload=Template:用戶沙盒/preload}} 您自己的沙盒]
* [[Wikipedia:關於沙盒|其他{{lan|zh-hans=资料|zh-hant=資料}}]]
{{div col end}}
}}
</div><div class="abusefilter-sandbox-header"></div><includeonly>
{{#switch:{{FULLPAGENAME}}
| Category:沙盒 = {{hiddencat}}
[[Category:維基百科管理]]
| #default = {{#ifeq:{{NAMESPACE}}|User||{{#ifeq:{{NAMESPACE}}|User talk||{{#if:{{{8|}}}||[[Category:沙盒]]}}}}}}
}}</includeonly>
{{{editnotice|
----}}}<noinclude>
{{doc}}
</noinclude>
f2ad992b81199261b0c806fb320939944a642b1a
Module:Citation/CS1/Configuration
828
176
358
2024-07-11T09:05:27Z
zhwp>Shizhao
0
ep
Scribunto
text/plain
local citation_config = {};
-- override <code>...</code> styling to remove color, border, and padding. <code> css is specified here:
-- https://git.wikimedia.org/blob/mediawiki%2Fcore.git/69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199
local code_style="color:inherit; border:inherit; padding:inherit;";
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------
List of namespaces that should not be included in citation error categories. Same as setting notracking = true by default
Note: Namespace names should use underscores instead of spaces.
]]
local uncategorized_namespaces = { 'User', 'Talk', 'User_talk', 'Wikipedia_talk', 'File_talk', 'Template_talk',
'Help_talk', 'Category_talk', 'Portal_talk', 'Book_talk', 'Draft', 'Draft_talk', 'Education_Program_talk',
'Module_talk', 'MediaWiki_talk' };
local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases'}; -- list of Lua patterns found in page names of pages we should not categorize
--[[--------------------------< M E S S A G E S >--------------------------------------------------------------
Translation table
The following contains fixed text that may be output as part of a citation.
This is separated from the main body to aid in future translations of this
module.
]]
local messages = {
['_safe_for_italics'] = {'lay source'},
['archived-dead'] = '($1存档于$2)',
['archived-not-dead'] = '(原始内容$1于$2)',
['archived-missing'] = '(原始内容$1存档于$2)',
['archived-unfit'] = '原始内容存档于$1',
['archived'] = '存档',
['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword
['cartography'] = 'Cartography by $1',
['docket'] = 'Docket $1',
['editor'] = '编',
['editors'] = '编',
['edition'] = ' $1',
['episode'] = '第$1集',
['et al'] = 'et al',
['in'] = '(编)', -- edited works
['inactive'] = '不活跃',
['interview'] = ' $1 with $2',
['inset'] = '$1 inset',
['lay summary'] = '简明摘要',
['lay source'] = " – ''$1''",
['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1',
['original'] = '原始内容',
['orig year'] = ' [$1]',
['published'] = '$1',
['retrieved'] = '[$1]',
['season'] = '第$1季',
['section'] = '§ $1',
['sections'] = '§§ $1',
['series'] = '第$1系列',
['thesis with type'] = '$1论文',
['thesis no type'] = '学位论文',
['translated'] = '由$1翻译',
['type'] = ' ($1)', -- for titletype
['written'] = ' 写于$1',
['vol'] = '$1 Vol. $2', -- $1 is sepc; bold journal style volume is in presentation{}
['vol-no'] = '$1 Vol. $2 no. $3', -- sepc, volume, issue
['issue'] = '$1 No. $2', -- $1 is sepc
['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{}
['j-issue'] = ' ($1)',
['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc
['p-prefix'] = ": $2", -- $1 is sepc
['pp-prefix'] = ": $2", -- $1 is sepc
['j-page(s)'] = ': $1', -- same for page and pages
['sheet'] = '$1 Sheet $2', -- $1 is sepc
['sheets'] = '$1 Sheets $2', -- $1 is sepc
['j-sheet'] = ': Sheet $1',
['j-sheets'] = ': Sheets $1',
['language'] = '<span style="font-family: sans-serif; cursor: default; color:var(--color-subtle, #54595d); font-size: 0.8em; bottom: 0.1em; font-weight: bold;" title="连接到$1网页">($1)</span>',
['via'] = " –-{zh-hans:通过;zh-hant:透過;}-$1",
['event'] = ' 事件发生在 $1',
['minutes'] = ' $1 记录于',
['parameter-separator'] = '、',
['parameter-final-separator'] = '和',
['parameter-pair-separator'] = '和',
['publication-date'] = ' ($1)',
-- Determines the location of the help page
['help page link'] = 'Help:引文格式1错误',
['help page label'] = '帮助',
['maintenance-link'] = 'link',
['maintenance-item'] = ' $1 ($2)'
}
--[[--------------------------< I N T E R N A L _ E R R O R S >-------------------------------------------
Internal errors (should only occur if configuration is bad)
]]
local internal_errors = {
['undefined_error'] = '调用了一个未定义的错误条件',
['unknown_manual_ID'] = '无法识别的手动ID模式',
['unknown_ID_mode'] = '无法识别的ID模式',
['unknown_argument_map'] = '检测到参数别名与参数名之间的映射丢失',
['bad_link_no_origin'] = '检测到格式错误但源头不明的内部链接',
['bad_url_no_origin'] = '检测到格式错误但源头不明的网址',
['bare_url_no_origin'] = '检测到源头不明的裸网址',
}
--[[--------------------------< P R E S E N T A T I O N >------------------------------------------------------
Fixed presentation markup. Originally part of citation_config.messages it has been moved into its own, more semantically
correct place.
]]
local presentation = {
['_safe_for_italics'] = {'italic-title', 'trans-italic-title'},
-- Error output
-- .error class is specified at https://git.wikimedia.org/blob/mediawiki%2Fcore.git/9553bd02a5595da05c184f7521721fb1b79b3935/skins%2Fcommon%2Fshared.css#L538
-- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display
['hidden-error'] = '<span style="display:none;font-size:100%" class="error citation-comment">$1</span>',
['visible-error'] = '<span style="font-size:100%" class="error citation-comment">$1</span>',
['accessdate'] = ' <span class="reference-accessdate">$2</span>', -- to allow editors to hide accessdate using personal css
['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like
['format'] = ' <span style="font-size:85%;">($1)</span>', -- for |format=, |chapter-format=, etc
['access-signal'] = '<span class="plainlinks">$1 $2</span>', -- external link with appropriate lock icon
['free'] = '[[File:Lock-green.svg|9px|link=|alt=可免费查阅|可免费查阅]]',
['registration'] = '[[File:Lock-blue-alt-2.svg|9px|link=|alt=需要免费注册|需要免费注册]]',
['limited'] = '[[File:Lock-blue-alt-2.svg|9px|link=|alt=有限度免费查阅,超限则需付费订阅|有限度免费查阅,超限则需付费订阅]]',
['subscription'] = '[[File:Lock-red-alt.svg|9px|link=|alt=需要付费订阅|需要付费订阅]]',
['italic-title'] = "$1",
['kern-left'] = '<span style="padding-left:0.2em;">$1</span>$2', -- spacing to use when title contains leading single or double quote mark
['kern-right'] = '$1<span style="padding-right:0.2em;">$2</span>', -- spacing to use when title contains trailing single or double quote mark
['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span>
['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space)
['OCinS'] = '<span title="$1" class="Z3988"><span style="display:none;"> </span></span>',
-- Note: Using display: none on the COinS span breaks some clients.
['parameter'] = '<code style="'..code_style..'">|$1=</code>',
['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content
['quoted-title'] = '$1',
['trans-italic-title'] = "[$1]",
['trans-quoted-title'] = "[$1]",
['vol-bold'] = ' <b>$1</b>', -- for journal cites; for other cites ['vol'] in messages{}
['maintenance'] = '<span class="citation-comment" style="display:none; color:#33aa33">$1</span>',
['citation-with-id'] = '<cite id="$1" class="$2">$3</cite>',
['citation-no-id'] = '<cite class="$1">$2</cite>'
}
--[[--------------------------< P E R I O D I C A L _ P A R A M E T E R S >-----------------------------------
用于整理periodical系列参数的别名,key为对应的citation class。在主模块中推断{{citation}}的引用类型时会用到。
]]
local periodical_parameters = {
['journal'] = {'journal'},
['news'] = {'newspaper'},
['magazine'] = {'magazine'},
['web'] = {'website'},
['encyclopaedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'},
['mailinglist'] = {'mailinglist', 'mailing-list'},
['_general'] = {'work', 'periodical'}
} -- 注意参数排列顺序,_general一定要放最后。
local periodical_compatibility = {
['journal'] = {
['drop'] = {'news', 'encyclopaedia', 'mailinglist'},
['warn'] = {'magazine'},
['suggest'] = 'journal'
},
['news'] = {
['drop'] = {'encyclopaedia', 'mailinglist', 'journal'},
['warn'] = {'magazine'},
['suggest'] = 'newspaper'
},
['magazine'] = {
['drop'] = {'encyclopaedia', 'mailinglist'},
['warn'] = {'journal', 'news'},
['suggest'] = 'magazine'
},
['web'] = {
['drop'] = {'encyclopaedia', 'mailinglist'},
['warn'] = {'news', 'journal', 'magazine'},
['suggest'] = 'website'
},
['encyclopaedia'] = {
['drop'] = {'mailinglist', 'news', 'journal', 'magazine'},
},
['mailinglist'] = {
['drop'] = {'encyclopaedia', 'news', 'journal', 'magazine', 'web'},
},
['book'] = {
['drop'] = {'news', 'journal', 'mailinglist'},
['warn'] = {'encyclopaedia', 'magazine'},
['suggest'] = 'work'
},
['conference'] = {
['drop'] = {'news', 'magazine', 'mailinglist', 'encyclopaedia'},
['warn'] = {'journal'},
['suggest'] = 'book-title'
},
['map'] = {
['drop'] = {'mailinglist', 'encyclopaedia'},
},
['interview'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal'},
},
['AV media'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine'},
},
['podcast'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['serial'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['speech'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine'},
},
['episode'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['thesis'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'news'},
},
['pressrelease'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'journal'},
},
['arxiv'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'journal', 'web'}
}
}
local function build_periodical ()
local periodical_items = {};
for _, aliases in pairs (periodical_parameters) do
for _, aliase in pairs (aliases) do
table.insert (periodical_items, aliase);
end
end
return periodical_items;
end
local periodical = {
parameters = periodical_parameters,
compatibility = periodical_compatibility
}
--[[--------------------------< A L I A S E S >----------------------------------------------------------------
Aliases table for commonly passed parameters
]]
local aliases = {
['AccessDate'] = {'access-date', 'accessdate'},
['Agency'] = 'agency',
['AirDate'] = {'air-date', 'airdate'},
['ArchiveDate'] = {'archive-date', 'archivedate'},
['ArchiveFormat'] = 'archive-format',
['ArchiveURL'] = {'archive-url', 'archiveurl'},
['ASINTLD'] = {'ASIN-TLD', 'asin-tld'},
['At'] = 'at',
['Authors'] = {'authors', 'people', 'host', 'credits'},
['BookTitle'] = {'book-title', 'booktitle'},
['Callsign'] = {'call-sign', 'callsign'}, -- cite interview
['Cartography'] = 'cartography',
['Chapter'] = {'chapter', 'contribution'},
['ChapterFormat'] = {'chapter-format', 'contribution-format', 'section-format'};
['ChapterURL'] = {'chapter-url', 'chapterurl', 'contribution-url', 'contributionurl', 'section-url', 'sectionurl'},
['ChapterUrlAccess'] = {'chapter-url-access', 'section-url-access'};
['City'] = 'city', -- cite interview
['Class'] = 'class', -- cite arxiv and arxiv identifiers
['Coauthors'] = {'coauthors', 'coauthor'}, -- coauthor and coauthors are deprecated; remove after 1 January 2015?
['Conference'] = {'conference', 'event'},
['ConferenceFormat'] = {'conference-format', 'event-format'},
['ConferenceURL'] = {'conference-url', 'conferenceurl', 'event-url', 'eventurl'},
['Contribution'] = 'contribution', -- introduction, foreword, afterword, etc; required when |contributor= set
['Date'] = 'date',
['DeadURL'] = {'dead-url', 'deadurl','url-status','urlstatus'},
['Degree'] = 'degree',
['DF'] = 'df',
['DisplayAuthors'] = {'display-authors', 'displayauthors'},
['DisplayEditors'] = {'display-editors', 'displayeditors'},
['Docket'] = 'docket',
['DoiBroken'] = {'doi-broken', 'doi-broken-date', 'doi-inactive-date', 'doi_brokendate', 'doi_inactivedate'},
['Edition'] = 'edition',
['Editors'] = 'editors',
['Embargo'] = 'embargo',
['Entry'] = {'entry', 'article'}, -- cite encyclopedia only
['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode?
['Format'] = 'format',
['ID'] = {'id', 'ID'},
['IgnoreISBN'] = {'ignore-isbn-error', 'ignoreisbnerror'},
['Inset'] = 'inset',
['Issue'] = {'issue', 'number'},
['Language'] = {'language', 'in'},
['LastAuthorAmp'] = {'last-author-amp', 'lastauthoramp'},
['LayDate'] = {'lay-date', 'laydate'},
['LayFormat'] = 'lay-format',
['LaySource'] = {'lay-source', 'laysource'},
['LayURL'] = {'lay-url', 'lay-summary', 'layurl', 'laysummary'},
['Map'] = 'map', -- cite map only
['MapFormat'] = 'map-format', -- cite map only
['MapURL'] = {'mapurl', 'map-url'}, -- cite map only
['MapUrlAccess'] = {'map-url-access'}, -- cite map only
['MessageID'] = 'message-id',
['Minutes'] = 'minutes',
['Mode'] = 'mode',
['NameListFormat'] = {'name-list-format','name-list-style'},
['Network'] = 'network',
['NoPP'] = {'no-pp', 'nopp'},
['NoTracking'] = {'template-doc-demo', 'template doc demo', 'no-cat', 'nocat',
'no-tracking', 'notracking'},
['Number'] = 'number', -- this case only for cite techreport
['OrigYear'] = {'orig-year', 'origyear'},
['Others'] = {'others', 'interviewer', 'interviewers'},
['Page'] = {'p', 'page'},
['Pages'] = {'pp', 'pages'},
['Periodical'] = build_periodical (),
['Place'] = {'place', 'location'},
['Program'] = 'program', -- cite interview
['PostScript'] = 'postscript',
['PublicationDate'] = {'publicationdate', 'publication-date'},
['PublicationPlace'] = {'publication-place', 'publicationplace'},
['PublisherName'] = {'publisher', 'distributor', 'institution', 'newsgroup'},
['Quote'] = {'quote', 'quotation'},
['Ref'] = 'ref',
['RegistrationRequired'] = 'registration',
['Scale'] = 'scale',
['ScriptChapter'] = 'script-chapter',
['ScriptTitle'] = 'script-title',
['Section'] = 'section',
['Sections'] = 'sections', -- cite map only
['Season'] = 'season',
['Series'] = {'series', 'version'},
['SeriesSeparator'] = 'series-separator',
['SeriesLink'] = {'series-link', 'serieslink'},
['SeriesNumber'] = {'series-number', 'series-no', 'seriesnumber', 'seriesno'},
['Sheet'] = 'sheet', -- cite map only
['Sheets'] = 'sheets', -- cite map only
['Station'] = 'station',
['SubscriptionRequired'] = 'subscription',
['Time'] = 'time',
['TimeCaption'] = {'time-caption', 'timecaption'},
['Title'] = 'title',
['TitleLink'] = {'title-link', 'episode-link', 'titlelink', 'episodelink'},
['TitleNote'] = 'department',
['TitleType'] = {'type', 'medium'},
['TransChapter'] = {'trans-chapter', 'trans_chapter'},
['TransMap'] = 'trans-map', -- cite map only
['Transcript'] = 'transcript',
['TranscriptFormat'] = 'transcript-format',
['TranscriptURL'] = {'transcript-url', 'transcripturl'},
['TransTitle'] = {'trans-title', 'trans_title', 'title_zh'},
['URL'] = {'url', 'URL'},
['UrlAccess']={'url-access','urlaccess'},
['Vauthors'] = 'vauthors',
['Veditors'] = 'veditors',
['Via'] = 'via',
['Volume'] = 'volume',
['Year'] = 'year',
['AuthorList-First'] = {"first#", "given#", "author-first#", "author#-first"},
['AuthorList-Last'] = {"last#", "author#", "surname#", "author-last#", "author#-last", "subject#"},
['AuthorList-Link'] = {"authorlink#", "author-link#", "author#-link", "subjectlink#", "author#link", "subject-link#", "subject#-link", "subject#link"},
['AuthorList-Mask'] = {"author-mask#", "authormask#", "author#mask", "author#-mask"},
['ContributorList-First'] = {'contributor-first#','contributor#-first'},
['ContributorList-Last'] = {'contributor#', 'contributor-last#', 'contributor#-last'},
['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'},
['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'},
['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"},
['EditorList-Last'] = {"editor#", "editor-last#", "editor#-last", "editor-surname#", "editor#-surname"},
['EditorList-Link'] = {"editor-link#", "editor#-link", "editorlink#", "editor#link"},
['EditorList-Mask'] = {"editor-mask#", "editor#-mask", "editormask#", "editor#mask"},
['TranslatorList-First'] = {'translator-first#','translator#-first'},
['TranslatorList-Last'] = {'translator#', 'translator-last#', 'translator#-last'},
['TranslatorList-Link'] = {'translator-link#', 'translator#-link'},
['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'},
}
--[[--------------------------< D E F A U L T S >--------------------------------------------------------------
Default parameter values
TODO: keep this? Only one default?
]]
local defaults = {
['DeadURL'] = 'yes',
}
--[[--------------------------< A R G S _ S U P P O R T >-----------------------------------------------------
These tables hold cite class values (from the template invocation) and identify those templates that support or require
certain parameters.
]]
local args_support = {
['templates_using_volume'] = {'citation', 'AV media', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'},
['templates_using_issue'] = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news'},
['templates_not_using_page'] = {'AV media', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'},
['templates_involving_time'] = {'AV media', 'episode', 'speech', 'podcast', 'serial'},
['templates_not_using_chapter'] = {'encyclopaedia', 'web', 'news', 'journal', 'magazine', 'pressrelease','podcast', 'newsgroup', 'mailinglist', 'map', 'conference', 'episode', 'serial', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'},
['templates_not_using_chapter_format'] = {'web', 'news', 'journal', 'magazine', 'pressrelease','podcast', 'newsgroup', 'mailinglist', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'},
['templates_using_contributor'] = {'book', 'citation'}, -- |contributor= and |contribution= only supported in book cites
['templates_requiring_url'] = {'web', 'podcast', 'mailinglist'}
}
--[[--------------------------< K E Y W O R D S >--------------------------------------------------------------
This table holds keywords for those parameters that have defined sets of acceptible keywords.
]]
local keywords = {
['yes_true_y'] = {'yes', 'true', 'y'}, -- ignore-isbn-error, last-author-amp, no-tracking, nopp, registration, subscription
['deadurl'] = {'yes', 'true', 'y', 'dead', 'no', 'live', 'unfit', 'usurped'},
['deadurl-live'] = {'no', 'live'},
['deadurl-unfit'] = {'unfit', 'usurped'},
['mode'] = {'cs1', 'cs2'},
['name-list-format'] = {'vanc', 'amp', '&'},
['contribution'] = {'afterword', 'foreword', 'introduction', 'preface'}, -- generic contribution titles that are rendered unquoted in the 'chapter' position
['date-format'] = {'dmy', 'dmy-all', 'mdy', 'mdy-all', 'ymd', 'ymd-all'},
['id-access'] = {'free'},
['url-access'] = {'free', 'limited', 'subscription', 'registration'},
}
--[[--------------------------< I N V I S I B L E _ C H A R A C T E R S >--------------------------------------
This table holds non-printing or invisible characters indexed either by name or by Unicode group. Values are decimal
representations of UTF-8 codes. The table is organized as a table of tables because the lua pairs keyword returns
table data in an arbitrary order. Here, we want to process the table from top to bottom because the entries at
the top of the table are also found in the ranges specified by the entries at the bottom of the table.
This list contains patterns for templates like {{'}} which isn't an error but transcludes characters that are
invisible. These kinds of patterns must be recognized by the functions that use this list.
Also here is a pattern that recognizes stripmarkers that begin and end with the delete characters. The nowiki
stripmarker is not an error but some others are because the parameter values that include them become part of the
template's metadata before stripmarker replacement.
]]
local invisible_chars = {
{'replacement', '\239\191\189', '替换字符'}, -- U+FFFD, EF BF BD
{'apostrophe', '‍\226\128\138\039\226\128\139', '撇号'}, -- apostrophe template: ‍ hair space ' zero-width space; not an error
{'apostrophe', '\226\128\138\039\226\128\139', '撇号'}, -- apostrophe template: hair space ' zero-width space; (as of 2015-12-11) not an error
{'zero width joiner', '\226\128\141', '零宽连字'}, -- U+200D, E2 80 8D
{'zero width space', '\226\128\139', '零宽空格'}, -- U+200B, E2 80 8B
{'hair space', '\226\128\138', '字间最小间隔'}, -- U+200A, E2 80 8A
{'soft hyphen', '\194\173', '软连字符'}, -- U+00AD, C2 AD
{'horizontal tab', '\009', '水平制表'}, -- U+0009 (HT), 09
{'line feed', '\010', '換行符'}, -- U+0010 (LF), 0A
{'carriage return', '\013', '回车符'}, -- U+0013 (CR), 0D
-- {'nowiki stripmarker', '\127UNIQ%-%-nowiki%-[%a%d]+%-QINU\127'}, -- nowiki stripmarker; not an error
{'stripmarker', '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', 'mediawiki占位符'},
-- stripmarker; may or may not be an error; capture returns the stripmaker type
{'delete', '\127', '删除符'}, -- U+007F (DEL), 7F; must be done after stripmarker test
{'C0 control', '[\000-\008\011\012\014-\031]', 'C0控制符'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D))
{'C1 control', '[\194\128-\194\159]', 'C1控制符'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F
{'Specials', '[\239\191\185-\239\191\191]', '特殊字符'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF
{'Private use area', '[\238\128\128-\239\163\191]', '私用空间'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF
{'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]',
'补充私用空间A'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD
{'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]',
'补充私用空间B'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD
}
--[[--------------------------< E X T R A _ T E X T _ P A T T E R N >--------------------------------------
]]
local extra_text_pattern = {
['edition'] = {
['good'] = {
},
['bad'] = {
'%f[%a][Ee]d%.?$',
'%f[%a][Ee]dition$'
}
},
['page'] = {
['good'] = {
'^P[^%.Pp]' -- ok to begin with uppercase P: P7 (pg 7 of section P) but not p123 (page 123) TODO: add Gg for PG or Pg?
},
['bad'] = {
'^[Pp]?[Pp]%.?[ %d]',
'^[Pp]ages?'
}
}
}
--[[---------------------< S T R I P M A R K E R S >----------------------------
Common pattern definition location for stripmarkers so that we don't have to go
hunting for them if (when) MediaWiki changes their form.
]]
local stripmarkers = {
['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker
['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker()
}
local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]';
--[[--------------------------< M A I N T E N A N C E _ C A T E G O R I E S >----------------------------------
Here we name maintenance categories to be used in maintenance messages.
]]
local maint_cats = {
['ASIN'] = '引文格式1维护:ASIN使用ISBN',
['date_year'] = '引文格式1维护:日期与年',
['disp_auth_ed'] = '引文格式1维护:显示-作者', -- $1 is authors or editors
['embargo'] = '引文格式1维护:PMC封锁过期',
['english'] = 'CS1 maint: English language specified',
['etal'] = '引文格式1维护:显式使用等标签',
['extra_text'] = '引文格式1维护:冗余文本',
['ignore_isbn_err'] = '引文格式1维护:ISBN错误被忽略',
['jfm_format'] = '引文格式1维护:jfm格式',
['mr_format'] = '引文格式1维护:MR格式',
['pmc_format'] = '引文格式1维护:PMC格式',
['unknown_lang'] = '引文格式1维护:未识别语文类型',
['untitled'] = '引文格式1维护:无标题期刊',
['zbl_format'] = '引文格式1维护:zbl格式',
['registration'] = '含有內容需登入查看的頁面',
['subscription'] = '含有連結內容需訂閱查看的頁面'
}
--[[--------------------------< P R O P E R T I E S _ C A T E G O R I E S >------------------------------------
Here we name properties categories
]]
local prop_cats = {
['foreign_lang_source'] = 'CS1$1来源 ($2)', -- |language= categories; $1 is language name, $2 is ISO639-1 code
['script'] = 'CS1含有外文文本', -- when language specified by |script-title=xx: doesn't have its own category
['script_with_name'] = 'CS1含有$1文本 ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is ISO639-1 code
}
--[[--------------------------< T I T L E _ T Y P E S >--------------------------------------------------------
Here we map a template's CitationClass to TitleType (default values for |type= parameter)
]]
local title_types = {
['AV media notes'] = '音像媒体说明',
['interview'] = '访谈',
['mailinglist'] = '邮件列表',
['map'] = '地图',
['podcast'] = '-{zh-cn:播客; zh-tw:Podcast;}-',
['pressrelease'] = '新闻稿',
['report'] = '报告',
['speech'] = '演讲',
['techreport'] = '技术报告',
['thesis'] = '学位论文'
}
--[[--------------------------< E R R O R _ C O N D I T I O N S >----------------------------------------------
Error condition table
The following contains a list of IDs for various error conditions defined in the code. For each ID, we specify a
text message to display, an error category to include, and whether the error message should be wrapped as a hidden comment.
Anchor changes require identical changes to matching anchor in Help:CS1 errors
]]
local error_conditions = {
accessdate_missing_url = {
message = '使用<code style="'..code_style..'">|accessdate=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'accessdate_missing_url',
category = '含有访问日期但无网址的引用的页面',
hidden = true },
archive_missing_date = {
message = '使用<code style="'..code_style..'">|archiveurl=</code>需要含有<code style="'..code_style..'">|archivedate=</code>',
anchor = 'archive_missing_date',
category = '含有存档网址错误的引用的页面',
hidden = false },
archive_missing_url = {
message = '使用<code style="'..code_style..'">|archiveurl=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'archive_missing_url',
category = '含有存档网址错误的引用的页面',
hidden = false },
arxiv_missing = {
message = '需要使用<code style="'..code_style..'">|arxiv=</code>',
anchor = 'arxiv_missing',
category = '引文格式1错误:arXiv', -- same as bad arxiv
hidden = false },
arxiv_params_not_supported = {
message = 'cite arXiv模板填写了不支持的参数',
anchor = 'arxiv_params_not_supported',
category = '引文格式1错误:arXiv', -- same as bad arxiv
hidden = false },
bad_arxiv = {
message = '请检查<code style="'..code_style..'">|arxiv=</code>值',
anchor = 'bad_arxiv',
category = '引文格式1错误:arXiv',
hidden = false },
bad_asin = {
message = '请检查<code style="'..code_style..'">|asin=</code>值',
anchor = 'bad_asin',
category ='引文格式1错误:ASIN',
hidden = false },
bad_bibcode = {
message = '请检查<code style="'..code_style..'">|bibcode=</code>值',
anchor = 'bad_bibcode',
category = '引文格式1错误:bibcode',
hidden = false },
bad_biorxiv = {
message = '请检查<code style="'..code_style..'">|biorxiv=</code>值',
anchor = 'bad_biorxiv',
category = '引文格式1错误:bioRxiv',
hidden = false },
bad_citeseerx = {
message = '请检查<code style="'..code_style..'">|citeseerx=</code>的值',
anchor = 'bad_citeseerx',
category = '引文格式1错误:citeseerx',
hidden = false },
bad_cnid = {
message = '请检查<code style="'..code_style..'">|cn=</code>的值',
anchor = 'bad_cnid',
category = '引文格式1错误:CN',
hidden = false },
bad_date = {
message = '请检查<code style="'..code_style..'">$1</code>中的日期值',
anchor = 'bad_date',
category = '引文格式1错误:日期',
hidden = true },
bad_doi = {
message = '请检查<code style="'..code_style..'">|doi=</code>值',
anchor = 'bad_doi',
category = '引文格式1错误:DOI',
hidden = false },
bad_hdl = {
message = '请检查<code style="'..code_style..'">|hdl=</code>值',
anchor = 'bad_hdl',
category = '引文格式1错误:HDL',
hidden = false },
bad_isbn = {
message = '请检查<code style="'..code_style..'">|isbn=</code>值',
anchor = 'bad_isbn',
category = '含有ISBN错误的引用的页面',
hidden = false },
bad_ismn = {
message = '请检查<code style="'..code_style..'">|ismn=</code>值',
anchor = 'bad_ismn',
category = '引文格式1错误:ISMN',
hidden = false },
bad_issn = {
message = '请检查<code style="'..code_style..'">|issn=</code>值',
anchor = 'bad_issn',
category = '引文格式1错误:ISSN',
hidden = false },
bad_jfm = {
message = '请检查<code style="'..code_style..'">|jfm=</code>值',
anchor = 'bad_jfm',
category = '引文格式1错误:JFM',
hidden = false },
bad_lccn = {
message = '请检查<code style="'..code_style..'">|lccn=</code>值',
anchor = 'bad_lccn',
category = '引文格式1错误:LCCN',
hidden = false },
bad_message_id = {
message = '请检查<code style="'..code_style..'">|message-id=</code>值',
anchor = 'bad_message_id',
category = '引文格式1错误:message-id',
hidden = false },
bad_mr = {
message = '请检查<code style="'..code_style..'">|mr=</code>值',
anchor = 'bad_mr',
category = '引文格式1错误:MR',
hidden = false },
bad_oclc = {
message = '请检查<code style="'..code_style..'">|oclc=</code>值',
anchor = 'bad_oclc',
category = '引文格式1错误:OCLC',
hidden = false },
bad_ol = {
message = '请检查<code style="'..code_style..'">|ol=</code>值',
anchor = 'bad_ol',
category = '引文格式1错误:OL',
hidden = false },
bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link=
message = '请检查<code style="'..code_style..'">|$1=</code>值',
anchor = 'bad_paramlink',
category = '引文格式1错误:参数链接',
hidden = false },
bad_pmc = {
message = '请检查<code style="'..code_style..'">|pmc=</code>值',
anchor = 'bad_pmc',
category = '引文格式1错误:PMC',
hidden = false },
bad_pmid = {
message = '请检查<code style="'..code_style..'">|pmid=</code>值',
anchor = 'bad_pmid',
category = '引文格式1错误:PMID',
hidden = false },
bad_s2cid = {
message = '请检查<code style="'..code_style..'">|s2cid=</code>的值',
anchor = 'bad_s2cid',
category = '引文格式1错误:S2CID',
hidden = false },
bad_ssrn = {
message = '请检查<code style="'..code_style..'">|ssrn=</code>的值',
anchor = 'bad_ssrn',
category = '引文格式1错误:SSRN',
hidden = false },
bad_url = {
message = '请检查<code style="'..code_style..'">|$1=</code>值',
anchor = 'bad_url',
category = '含有网址格式错误的引用的页面',
hidden = false },
bare_url_missing_title = {
message = '<code style="'..code_style..'">|$1=</code>缺少标题',
anchor = 'bare_url_missing_title',
category = '含有裸露网址的引用的页面',
hidden = false },
bad_zbl = {
message = '请检查<code style="'..code_style..'">|zbl=</code>的值',
anchor = 'bad_zbl',
category = '引文格式1错误:ZBL',
hidden = false },
bad_csbn = {
message = '请检查<code style="'..code_style..'">|csbn=</code>或<code style="'..code_style..'">|unified=</code>的值',
anchor = 'bad_csbn',
category = '引文格式1错误:CSBN',
hidden = false },
class_ignored = {
message = '<code style="'..code_style..'">|class=</code>被忽略',
anchor = 'class_ignored',
category = '引文格式1错误:class参数被忽略',
hidden = false },
chapter_ignored = {
message = '<code style="'..code_style..'">|$1=</code>被忽略',
anchor = 'chapter_ignored',
category = '引文格式1错误:章节参数被忽略',
hidden = false },
citation_missing_title = {
message = '缺少或<code style="'..code_style..'">|title=</code>为空',
anchor = 'citation_missing_title',
category = '含有缺少标题的引用的页面',
hidden = false },
cite_web_url = {
-- this error applies to cite web and to cite podcast
message = '缺少或<code style="'..code_style..'">|url=</code>为空',
anchor = 'cite_web_url',
category = '含有缺少网址的网站引用的页面',
hidden = true },
coauthors_missing_author = {
message = '使用<code style="'..code_style..'">|coauthors=</code>需要含有<code style="'..code_style..'">|author=</code>',
anchor = 'coauthors_missing_author',
category = '引文格式1错误:无主作者的合作者',
hidden = false },
contributor_ignored = {
message = '<code style="'..code_style..'">|contributor=</code>被忽略</code>',
anchor = 'contributor_ignored',
category = '引文格式1错误:合作者',
hidden = false },
contributor_missing_required_param = {
message = '使用<code style="'..code_style..'">|contributor=</code>需要含有<code style="'..code_style..'">|$1=</code>',
anchor = 'contributor_missing_required_param',
category = '引文格式1错误:合作者',
hidden = false },
date_year_mismatch = {
message = '<code style="'..code_style..'">|year=</code>与<code style="'..code_style..'">|$1=</code>不匹配',
anchor = 'date_year_mismatch',
category = '引文格式1错误:日期与年不匹配',
hidden = false },
deprecated_params = {
message = '引文使用过时参数<code style="'..code_style..'">$1</code>',
anchor = 'deprecated_params',
category = '含有过时参数的引用的页面',
hidden = true },
doi_inactive_dated = {
message = '自$1年含有不活躍DOI的頁面',
anchor = 'doi_inactive_dated',
category = '自$1年含有不活躍DOI的頁面',
hidden = true},
doi_inactive = {
message = '含有不活躍DOI的頁面',
anchor = 'doi_inactive_dated',
category = '含有不活躍DOI的頁面',
hidden = true},
empty_citation = {
message = '空引用',
anchor = 'empty_citation',
category = '含有空引用的页面',
hidden = false },
first_missing_last = {
message = '$1列表中的<code style="'..code_style..'">|first$2=</code>缺少<code style="'..code_style..'">|last$2=</code>',
anchor = 'first_missing_last',
category = '引文格式1错误:缺少作者或编者',
hidden = false },
format_missing_url = {
message = '使用<code style="'..code_style..'">|format=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'format_missing_url',
category = '含有格式却不含网址的引用的页面',
hidden = true },
implict_etal_editor = {
message = '建议使用<code style="'..code_style..'">|displayeditors=</code>',
anchor = 'displayeditors',
category = '含有旧式缩略标签的引用的页面 in editors',
hidden = true },
invalid_param_val = {
message = '无效<code style="'..code_style..'">|$1=$2</code>',
anchor = 'invalid_param_val',
category = '引文格式1错误:无效参数值',
hidden = false },
invisible_char = {
message = '参数$2值左起第$3位存在$1',
anchor = 'invisible_char',
category = '引文格式1错误:不可见字符',
hidden = false },
missing_name = {
message = '$1列表缺少<code style="'..code_style..'">|last$2=</code>',
anchor = 'missing_name',
category = '引文格式1错误:缺少作者或编者',
hidden = false },
param_access_requires_param = {
message = '使用<code style="'..code_style..'">|$1-access=</code>需要含有<code style="'..code_style..'">|$1=</code>',
anchor = 'param_access_requires_param',
category = '含有-access参数但无主参数的引用的页面',
hidden = true },
param_has_ext_link = {
message = '外部链接存在于<code style="'..code_style..'">$1</code>',
anchor = 'param_has_ext_link',
category = '引文格式1错误:外部链接',
hidden = false },
parameter_discarded = {
message = '<code style="'..code_style..'">|$1=</code>被忽略',
anchor = 'parameter_discarded',
category = '引文格式1错误:已知参数被忽略',
hidden = false },
parameter_ignored = {
message = '已忽略未知参数<code style="'..code_style..'">|$1=</code>',
anchor = 'parameter_ignored',
category = '含有未知参数的引用的页面',
hidden = false },
parameter_ignored_suggest = {
message = '已忽略未知参数<code style="'..code_style..'">|$1=</code>(建议使用<code style="'..code_style..'">|$2=</code>)',
anchor = 'parameter_ignored_suggest',
category = '含有未知参数的引用的页面',
hidden = false },
periodical = {
message = '参数<code style="'..code_style..'">|$1=</code>与模板<code style="'..code_style..'">{{cite $2}}</code>不匹配(建议改用<code style="'..code_style..'">{{cite $3}}</code>或<code style="'..code_style..'">|$4=</code>)',
anchor = 'periodical',
category = '引文格式1错误:periodical系列参数与模板类型不匹配',
hidden = false },
redundant_parameters = {
message = '$1只需其一',
anchor = 'redundant_parameters',
category = '含有冗余参数的引用的页面',
hidden = false },
text_ignored = {
message = '已忽略文本“$1”',
anchor = 'text_ignored',
category = '含有未命名参数的引用的页面',
hidden = false },
trans_missing_title = {
message = '使用<code style="'..code_style..'">|trans-title=</code>需要含有<code style="'..code_style..'">|title=</code>',
anchor = 'trans_missing_title',
category = '引文格式1错误:翻译标题',
hidden = false },
vancouver = {
message = '温哥华格式错误',
anchor = 'vancouver',
category = '引文格式1错误:温哥华格式',
hidden = false },
wikilink_in_url = {
message = '网址-维基内链冲突',
anchor = 'wikilink_in_url',
category = '引文格式1错误:网址-维基内链冲突',
hidden = false },
}
--[[--------------------------< I D _ H A N D L E R S >--------------------------------------------------------
The following contains a list of values for various defined identifiers. For each identifier we specify a
variety of information necessary to properly render the identifier in the citation.
parameters: a list of parameter aliases for this identifier
link: Wikipedia article name
label: the alternate name to apply to link
mode: 'manual' when there is a specific function in the code to handle the identifier;
'external' for identifiers that link outside of Wikipedia;
prefix: the first part of a url that will be concatenated with a second part which usually contains the identifier
encode: true if uri should be percent encoded; otherwise false
COinS: identifier link or keyword for use in COinS:
for identifiers registered at info-uri.info use: info:....
for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn
for others make a url using the value in prefix, use the keyword: pre (not checked; any text other than 'info' or 'rft' works here)
set to nil to leave the identifier out of the COinS
separator: character or text between label and the identifier in the rendered citation
]]
local id_handlers = {
['ARXIV'] = {
parameters = {'arxiv', 'ARXIV', 'eprint'},
link = 'arXiv',
label = 'arXiv',
mode = 'manual',
prefix = '//arxiv.org/abs/', -- protocol relative tested 2013-09-04
encode = false,
COinS = 'info:arxiv',
separator = ':',
access = 'free',
},
['ASIN'] = {
parameters = { 'asin', 'ASIN' },
link = '亚马逊标准识别码',
label = 'ASIN',
mode = 'manual',
prefix = '//www.amazon.',
COinS = nil, -- no COinS for this id (needs thinking on implementation because |asin-tld=)
separator = ' ',
encode = false;
},
['BIBCODE'] = {
parameters = {'bibcode', 'BIBCODE'},
link = 'Bibcode',
label = 'Bibcode',
mode = 'manual',
prefix = 'https://ui.adsabs.harvard.edu/abs/',
encode = false,
COinS = 'info:bibcode',
custom_access = 'bibcode-access',
separator = ':',
},
['BIORXIV'] = {
parameters = {'biorxiv'},
link = 'bioRxiv',
label = 'bioRxiv',
mode = 'manual',
prefix = '//doi.org/',
encode = true,
COinS = 'pre',
separator = ' ',
access = 'free',
},
['CITESEERX'] = {
parameters = {'citeseerx'},
link = 'CiteSeerX',
q = 'Q2715061',
label = 'CiteSeerX',
mode = 'manual',
prefix = '//citeseerx.ist.psu.edu/viewdoc/summary?doi=',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['CNID'] = {
parameters = {'cn', 'CN'},
link = '国内统一刊号',
label = "CN",
mode = 'manual',
prefix = 'http://www.nppa.gov.cn/nppa/publishing/view.shtml?&pubCode=',
encode = true,
separator = ' ',
},
['DOI'] = {
parameters = { 'doi', 'DOI' },
link = '數位物件識別號',
q = 'Q25670',
label = 'doi',
mode = 'manual',
prefix = '//doi.org/',
COinS = 'info:doi',
custom_access = 'doi-access',
separator = ':',
encode = true,
},
['EISSN'] = {
parameters = {'eissn', 'EISSN'},
link = 'International_Standard_Serial_Number#Electronic_ISSN',
label = 'eISSN',
mode = 'manual',
prefix = '//www.worldcat.org/issn/',
COinS = 'rft.eissn',
encode = false,
separator = ' ',
},
['HDL'] = {
parameters = { 'hdl', 'HDL' },
link = 'Handle System',
q = 'Q3126718',
label = 'hdl',
mode = 'manual',
prefix = '//hdl.handle.net/',
COinS = 'info:hdl',
custom_access = 'hdl-access',
separator = ':',
encode = true,
},
['ISBN'] = {
parameters = {'isbn', 'ISBN', 'isbn13', 'ISBN13'},
link = '国际标准书号',
label = 'ISBN',
mode = 'manual',
prefix = 'Special:BookSources/',
COinS = 'rft.isbn',
separator = ' ',
},
['ISMN'] = {
parameters = {'ismn', 'ISMN'},
link = 'International Standard Music Number',
label = 'ISMN',
mode = 'manual',
prefix = '', -- not currently used;
COinS = 'nil', -- nil because we can't use pre or rft or info:
separator = ' ',
},
['ISSN'] = {
parameters = {'issn', 'ISSN'},
link = '国际标准连续出版物号',
label = 'ISSN',
mode = 'manual',
prefix = '//www.worldcat.org/issn/',
COinS = 'rft.issn',
encode = false,
separator = ' ',
},
['JFM'] = {
parameters = {'jfm', 'JFM'},
link = 'Jahrbuch über die Fortschritte der Mathematik',
label = 'JFM',
mode = 'manual',
prefix = '//zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['JSTOR'] = {
parameters = {'jstor', 'JSTOR'},
link = 'JSTOR',
label = 'JSTOR',
mode = 'external',
prefix = '//www.jstor.org/stable/', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
custom_access = 'jstor-access',
encode = false,
separator = ' ',
},
['LCCN'] = {
parameters = {'LCCN', 'lccn'},
link = '美国国会图书馆控制码',
label = 'LCCN',
mode = 'manual',
prefix = 'http://lccn.loc.gov/',
COinS = 'info:lccn', -- use prefix value
encode = false,
separator = ' ',
},
['MR'] = {
parameters = {'MR', 'mr'},
link = '數學評論',
label = 'MR',
mode = 'manual',
prefix = '//www.ams.org/mathscinet-getitem?mr=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['OCLC'] = {
parameters = {'OCLC', 'oclc'},
link = 'OCLC',
label = 'OCLC',
mode = 'manual',
prefix = '//www.worldcat.org/oclc/',
COinS = 'info:oclcnum',
encode = true,
separator = ' ',
},
['OL'] = {
parameters = { 'ol', 'OL' },
link = '开放图书馆',
label = 'OL',
mode = 'manual',
prefix = '//openlibrary.org/',
COinS = nil, -- no COinS for this id (needs thinking on implementation because /authors/books/works/OL)
custom_access = 'ol-access',
separator = ' ',
endode = true,
},
['OSTI'] = {
parameters = {'OSTI', 'osti'},
link = '科学和技术信息办公室',
label = 'OSTI',
mode = 'external',
prefix = '//www.osti.gov/energycitations/product.biblio.jsp?osti_id=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
custom_access = 'osti-access',
encode = true,
separator = ' ',
},
['PMC'] = {
parameters = {'PMC', 'pmc'},
link = '公共医学中心',
label = 'PMC',
mode = 'manual',
prefix = '//www.ncbi.nlm.nih.gov/pmc/articles/PMC',
suffix = " ",
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
access = 'free',
},
['PMID'] = {
parameters = {'PMID', 'pmid'},
link = '公共医学识别码',
label = 'PMID',
mode = 'manual',
prefix = '//www.ncbi.nlm.nih.gov/pubmed/',
COinS = 'info:pmid',
encode = false,
separator = ' ',
},
['RFC'] = {
parameters = {'RFC', 'rfc'},
link = '徵求修正意見書',
label = 'RFC',
mode = 'external',
prefix = '//tools.ietf.org/html/rfc',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
access = 'free',
},
['S2CID'] = {
parameters = {'s2cid', 'S2CID'},
link = 'Semantic Scholar', -- l10n: Not created yet
label = 'S2CID',
mode = 'manual',
prefix = 'https://api.semanticscholar.org/CorpusID:',
COinS = 'pre', -- use prefix value
custom_access = 's2cid-access',
encode = false,
separator = ' ',
},
['SSRN'] = {
parameters = {'SSRN', 'ssrn'},
link = '社会科学研究网络',
label = 'SSRN',
mode = 'manual',
prefix = '//ssrn.com/abstract=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
access = 'free',
},
['USENETID'] = {
parameters = {'message-id'},
link = 'Usenet',
label = 'Usenet:',
mode = 'manual',
prefix = 'news:',
encode = false,
COinS = 'pre', -- use prefix value
separator = ' ',
},
['ZBL'] = {
parameters = {'ZBL', 'zbl'},
link = 'Zentralblatt MATH',
label = 'Zbl',
mode = 'manual',
prefix = '//zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
-- LOCAL
['CSBN'] = {
parameters = {'unified', 'csbn', 'CSBN'},
link = '统一书号',
label = 'CSBN',
mode = 'manual',
prefix = 'http://book.douban.com/subject_search?search_text=SH',
COinS = 'rft.csbn',
encode = true,
separator = ' ',
},
-- END LOCAL
}
return {
aliases = aliases,
args_support = args_support,
defaults = defaults,
error_conditions = error_conditions,
indic_script = indic_script,
internal_errors = internal_errors,
id_handlers = id_handlers,
keywords = keywords,
invisible_chars = invisible_chars,
extra_text_pattern = extra_text_pattern,
maint_cats = maint_cats,
messages = messages,
periodical = periodical,
presentation = presentation,
prop_cats = prop_cats,
stripmarkers = stripmarkers,
title_types = title_types,
uncategorized_namespaces = uncategorized_namespaces,
uncategorized_subpages = uncategorized_subpages,
}
d3306a3bbc1c9c3932fd2acd56c3ed70f5b08e8e
Module:Navbar/styles.css
828
117
228
2024-07-11T09:16:18Z
zhwp>Shizhao
0
ep
sanitized-css
text/css
.navbar {
display: inline;
font-weight: normal;
}
.navbar-collapse {
float: left;
text-align: left;
}
.navbar-boxtext {
word-spacing: 0;
}
.navbar ul {
display: inline-block;
white-space: nowrap;
line-height: inherit;
}
.navbar-brackets::before {
margin-right: -0.125em;
content: '[ ';
}
.navbar-brackets::after {
margin-left: -0.125em;
content: ' ]';
}
.navbar li {
word-spacing: -0.125em;
}
.navbar a > span,
.navbar a > abbr {
text-decoration: inherit;
}
.navbar-mini abbr {
font-variant: small-caps;
border-bottom: none;
text-decoration: none;
cursor: inherit;
}
.navbar-ct-full {
font-size: 114%;
margin: 0 7em;
}
.navbar-ct-mini {
font-size: 114%;
margin: 0 4em;
}
97042550467b3dbf0888cf32106715789682e887
Module:Navbar
828
78
150
2024-07-11T12:40:57Z
zhwp>Shizhao
0
自[[Module:Navbar/sandbox]]合并[[Special:Contributions/Dabao qian|Dabao qian]]的[[Special:PermaLink/83275381|版本83275381]]
Scribunto
text/plain
local p = {}
local cfg = mw.loadData('Module:Navbar/configuration')
local function get_title_arg(is_collapsible, template)
local title_arg = 1
if is_collapsible then title_arg = 2 end
if template then title_arg = 'template' end
return title_arg
end
local function choose_links(template, args)
-- The show table indicates the default displayed items.
-- view, talk, edit, hist, move, watch
-- TODO: Move to configuration.
local show = {true, true, true, false, false, false}
if template then
show[2] = false
show[3] = false
local index = {t = 2, d = 2, e = 3, h = 4, m = 5, w = 6,
talk = 2, edit = 3, hist = 4, move = 5, watch = 6}
-- TODO: Consider removing TableTools dependency.
for _, v in ipairs(require ('Module:TableTools').compressSparseArray(args)) do
local num = index[v]
if num then show[num] = true end
end
end
local remove_edit_link = args.noedit
if remove_edit_link then show[3] = false end
return show
end
local function add_link(link_description, ul, is_mini, font_style)
local l
if link_description.url then
l = {'[', '', ']'}
else
l = {'[[', '|', ']]'}
end
ul:tag('li')
:addClass('nv-' .. link_description.full)
:wikitext(l[1] .. link_description.link .. l[2])
:tag(is_mini and 'abbr' or 'span')
:attr('title', link_description.html_title)
:cssText(font_style)
:wikitext(is_mini and link_description.mini or link_description.full)
:done()
:wikitext(l[3])
:done()
end
local function make_list(title_text, has_brackets, displayed_links, is_mini, font_style)
local title = mw.title.new(mw.text.trim(title_text), cfg.title_namespace)
if not title then
error(cfg.invalid_title .. title_text)
end
local talkpage = title.talkPageTitle and title.talkPageTitle.fullText or ''
-- TODO: Get link_descriptions and show into the configuration module.
-- link_descriptions should be easier...
local link_descriptions = {
{ ['mini'] = '-{zh-hans:查;zh-hant:閱;}-', ['full'] = '-{zh-hans:查看;zh-hant:檢視;}-', ['html_title'] = '-{zh-hans:查看;zh-hant:檢視;}-该模板',
['link'] = title.fullText, ['url'] = false },
{ ['mini'] = '论', ['full'] = '讨论', ['html_title'] = '讨论该模板',
['link'] = talkpage, ['url'] = false },
{ ['mini'] = '编', ['full'] = '编辑', ['html_title'] = '编辑该模板',
['link'] = 'Special:EditPage/' .. title.fullText, ['url'] = false },
{ ['mini'] = '史', ['full'] = '历史', ['html_title'] = '该模板的历史',
['link'] = 'Special:PageHistory/' .. title.fullText, ['url'] = false },
{ ['mini'] = '移', ['full'] = '移动', ['html_title'] = '移动该模板',
['link'] = mw.title.new('Special:Movepage'):fullUrl('target='..title.fullText), ['url'] = true },
{ ['mini'] = '监', ['full'] = '监视', ['html_title'] = '监视该模板',
['link'] = title:fullUrl('action=watch'), ['url'] = true }
}
local ul = mw.html.create('ul')
if has_brackets then
ul:addClass(cfg.classes.brackets)
:cssText(font_style)
end
for i, _ in ipairs(displayed_links) do
if displayed_links[i] then add_link(link_descriptions[i], ul, is_mini, font_style) end
end
return ul:done()
end
function p._navbar(args)
-- TODO: We probably don't need both fontstyle and fontcolor...
local font_style = args.fontstyle
local font_color = args.fontcolor
local is_collapsible = args.collapsible
local is_mini = args.mini
local is_plain = args.plain
local collapsible_class = nil
if is_collapsible then
collapsible_class = cfg.classes.collapsible
if not is_plain then is_mini = 1 end
if font_color then
font_style = (font_style or '') .. '; color: ' .. font_color .. ';'
end
end
local navbar_style = args.style
local div = mw.html.create():tag('div')
div
:addClass(cfg.classes.navbar)
:addClass(cfg.classes.plainlinks)
:addClass(cfg.classes.horizontal_list)
:addClass(collapsible_class) -- we made the determination earlier
:cssText(navbar_style)
if is_mini then div:addClass(cfg.classes.mini) end
local box_text = (args.text or cfg.box_text) .. ''
-- the concatenated space guarantees the box text is separated
if not (is_mini or is_plain) then
div
:tag('span')
:addClass(cfg.classes.box_text)
:cssText(font_style)
:wikitext(box_text)
end
local template = args.template
local displayed_links = choose_links(template, args)
local has_brackets = args.brackets
local title_arg = get_title_arg(is_collapsible, template)
local title_text = args[title_arg] or (':' .. mw.getCurrentFrame():getParent():getTitle())
local list = make_list(title_text, has_brackets, displayed_links, is_mini, font_style)
div:node(list)
if is_collapsible then
local title_text_class
if is_mini then
title_text_class = cfg.classes.collapsible_title_mini
else
title_text_class = cfg.classes.collapsible_title_full
end
div:done()
:tag('div')
:addClass(title_text_class)
:cssText(font_style)
:wikitext(args[1])
end
local frame = mw.getCurrentFrame()
-- hlist -> navbar is best-effort to preserve old Common.css ordering.
return frame:extensionTag{
name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
} .. frame:extensionTag{
name = 'templatestyles', args = { src = cfg.templatestyles }
} .. tostring(div:done())
end
function p.navbar(frame)
return p._navbar(require('Module:Arguments').getArgs(frame))
end
return p
ea41e2eba702ca65d1f599ce2fe7ce148a30b192
Module:Message box/configuration
828
61
116
2024-07-12T20:51:29Z
zhwp>Xiplus-abot
0
已保护“[[Module:Message box/configuration]]”:高風險模板:1637884引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
local ambox = {
types = {
speedy = {
class = 'ambox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ambox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'ambox-content',
image = 'Ambox important.svg'
},
style = {
class = 'ambox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ambox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ambox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'ambox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
allowBlankParams = {'talk', 'sect', 'date', 'issue', 'fix', 'subst', 'hidden'},
allowSmall = true,
smallParam = 'left',
smallClass = 'mbox-small-left',
substCheck = true,
classes = {'metadata', 'ambox'},
usePlainlinksParam = true,
allowId = true,
imageEmptyCell = true,
imageCheckBlank = true,
imageSmallSize = '20x20px',
imageCellDiv = true,
useCollapsibleTextFields = true,
imageRightNone = true,
sectionDefault = '條目',
allowMainspaceCategories = true,
templateCategory = '條目訊息模板',
templateCategoryRequireName = true,
templateErrorCategory = '缺少參數的條目訊息模板',
templateErrorParamsToCheck = {'issue', 'fix', 'subst'}
}
local cmbox = {
types = {
speedy = {
class = 'cmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'cmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'cmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'cmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'cmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'cmbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'cmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'cmbox'},
usePlainlinksParam = true,
imageEmptyCell = true
}
local fmbox = {
types = {
warning = {
class = 'fmbox-warning',
image = 'Ambox warning pn.svg'
},
editnotice = {
class = 'fmbox-editnotice',
image = 'Information icon4.svg'
},
system = {
class = 'fmbox-system',
image = 'Information icon4.svg'
}
},
default = 'system',
showInvalidTypeError = true,
allowId = true,
classes = {'fmbox'},
usePlainlinksParam = true,
imageEmptyCell = false,
imageRightNone = false
}
local imbox = {
types = {
speedy = {
class = 'imbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'imbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'imbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'imbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'imbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'imbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
license = {
class = 'imbox-license',
image = 'Imbox license.png'
},
featured = {
class = 'imbox-featured',
image = 'Cscr-featured.svg'
},
notice = {
class = 'imbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'imbox'},
usePlainlinksParam = true,
imageEmptyCell = true,
below = true,
templateCategory = '檔案訊息模板'
}
local ombox = {
types = {
speedy = {
class = 'ombox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ombox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'ombox-content',
image = 'Ambox important.svg'
},
style = {
class = 'ombox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ombox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ombox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'ombox-notice',
image = 'Information icon4.svg'
},
note = {
class = 'ombox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'ombox'},
usePlainlinksParam = true,
allowSmall = true,
imageEmptyCell = true,
imageRightNone = true
}
local tmbox = {
types = {
speedy = {
class = 'tmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'tmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'tmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'tmbox-style',
image = 'Edit-clear.svg '
},
move = {
class = 'tmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'tmbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'tmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'tmbox'},
usePlainlinksParam = true,
allowId = true,
allowSmall = true,
imageRightNone = true,
imageEmptyCell = true,
imageEmptyCellStyle = true,
templateCategory = '討論訊息模板'
}
return {
ambox = ambox,
cmbox = cmbox,
fmbox = fmbox,
imbox = imbox,
ombox = ombox,
tmbox = tmbox
}
d6b253dd26d5c1b7843394d8c6756b0868e70b6c
Module:TableTools
828
72
138
2024-07-12T20:51:39Z
zhwp>Xiplus-abot
0
已保护“[[Module:TableTools]]”:高風險模板:405410引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
------------------------------------------------------------------------------------
-- TableTools --
-- --
-- This module includes a number of functions for dealing with Lua tables. --
-- It is a meta-module, meant to be called from other Lua modules, and should not --
-- be called directly from #invoke. --
------------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local p = {}
-- Define often-used variables and functions.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
function p.isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity
end
------------------------------------------------------------------------------------
-- isNan
--
-- This function returns true if the given number is a NaN value, and false if
-- not. Although it doesn't operate on tables, it is included here as it is useful
-- for determining whether a value can be a valid table key. Lua will generate an
-- error if a NaN is used as a table key.
------------------------------------------------------------------------------------
function p.isNan(v)
return type(v) == 'number' and v ~= v
end
------------------------------------------------------------------------------------
-- shallowClone
--
-- This returns a clone of a table. The value returned is a new table, but all
-- subtables and functions are shared. Metamethods are respected, but the returned
-- table will have no metatable of its own.
------------------------------------------------------------------------------------
function p.shallowClone(t)
checkType('shallowClone', 1, t, 'table')
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- This removes duplicate values from an array. Non-positive-integer keys are
-- ignored. The earliest value is kept, and all subsequent duplicate values are
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
function p.removeDuplicates(arr)
checkType('removeDuplicates', 1, arr, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for _, v in ipairs(arr) do
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
else
if not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
end
return ret
end
------------------------------------------------------------------------------------
-- numKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in numerical order.
------------------------------------------------------------------------------------
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- affixNums
--
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return
-- {1, 3, 6}.
------------------------------------------------------------------------------------
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- numData
--
-- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table
-- of subtables in the format
-- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}.
-- Keys that don't end with an integer are stored in a subtable named "other". The
-- compress option compresses the table so that it can be iterated over with
-- ipairs.
------------------------------------------------------------------------------------
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Positional parameters match the blank string; put them at the start of the subtable instead.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- This takes an array with one or more nil values, and removes the nil values
-- while preserving the order, so that the array can be safely traversed with
-- ipairs.
------------------------------------------------------------------------------------
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- This is an iterator for sparse arrays. It can be used like ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- size
--
-- This returns the size of a key/value pair table. It will also work on arrays,
-- but for arrays it is more efficient to use the # operator.
------------------------------------------------------------------------------------
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for _ in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then
return tostring(item1) < tostring(item2)
else
return item1 < item2
end
end
------------------------------------------------------------------------------------
-- keysToList
--
-- Returns an array of the keys in a table, sorted using either a default
-- comparison function or a custom keySort function.
------------------------------------------------------------------------------------
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'})
end
local arr = {}
local index = 1
for k in pairs(t) do
arr[index] = k
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(arr, keySort)
end
return arr
end
------------------------------------------------------------------------------------
-- sortedPairs
--
-- Iterates through a table, with the keys sorted using the keysToList function.
-- If there are only numerical keys, sparseIpairs is probably more efficient.
------------------------------------------------------------------------------------
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local arr = p.keysToList(t, keySort, true)
local i = 0
return function ()
i = i + 1
local key = arr[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- isArray
--
-- Returns true if the given value is a table and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArray(v)
if type(v) ~= 'table' then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- isArrayLike
--
-- Returns true if the given value is iterable and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArrayLike(v)
if not pcall(pairs, v) then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- invert
--
-- Transposes the keys and values in an array. For example, {"a", "b", "c"} ->
-- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to
-- the index of the last duplicate) and NaN values are ignored.
------------------------------------------------------------------------------------
function p.invert(arr)
checkType("invert", 1, arr, "table")
local isNan = p.isNan
local map = {}
for i, v in ipairs(arr) do
if not isNan(v) then
map[v] = i
end
end
return map
end
------------------------------------------------------------------------------------
-- listToSet
--
-- Creates a set from the array part of the table. Indexing the set by any of the
-- values of the array returns true. For example, {"a", "b", "c"} ->
-- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them
-- never equal to any value (including other NaNs or even themselves).
------------------------------------------------------------------------------------
function p.listToSet(arr)
checkType("listToSet", 1, arr, "table")
local isNan = p.isNan
local set = {}
for _, v in ipairs(arr) do
if not isNan(v) then
set[v] = true
end
end
return set
end
------------------------------------------------------------------------------------
-- deepCopy
--
-- Recursive deep copy function. Preserves identities of subtables.
------------------------------------------------------------------------------------
local function _deepCopy(orig, includeMetatable, already_seen)
-- Stores copies of tables indexed by the original table.
already_seen = already_seen or {}
local copy = already_seen[orig]
if copy ~= nil then
return copy
end
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen)
end
already_seen[orig] = copy
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
local mt_copy = _deepCopy(mt, includeMetatable, already_seen)
setmetatable(copy, mt_copy)
already_seen[mt] = mt_copy
end
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen)
end
------------------------------------------------------------------------------------
-- sparseConcat
--
-- Concatenates all values in the table that are indexed by a number, in order.
-- sparseConcat{a, nil, c, d} => "acd"
-- sparseConcat{nil, b, c, d} => "bcd"
------------------------------------------------------------------------------------
function p.sparseConcat(t, sep, i, j)
local arr = {}
local arr_i = 0
for _, v in p.sparseIpairs(t) do
arr_i = arr_i + 1
arr[arr_i] = v
end
return table.concat(arr, sep, i, j)
end
------------------------------------------------------------------------------------
-- length
--
-- Finds the length of an array, or of a quasi-array with keys such as "data1",
-- "data2", etc., using an exponential search algorithm. It is similar to the
-- operator #, but may return a different value when there are gaps in the array
-- portion of the table. Intended to be used on data loaded with mw.loadData. For
-- other tables, use #.
-- Note: #frame.args in frame object always be set to 0, regardless of the number
-- of unnamed template parameters, so use this function for frame.args.
------------------------------------------------------------------------------------
function p.length(t, prefix)
-- requiring module inline so that [[Module:Exponential search]] which is
-- only needed by this one function doesn't get millions of transclusions
local expSearch = require("Module:Exponential search")
checkType('length', 1, t, 'table')
checkType('length', 2, prefix, 'string', true)
return expSearch(function (i)
local key
if prefix then
key = prefix .. tostring(i)
else
key = i
end
return t[key] ~= nil
end) or 0
end
------------------------------------------------------------------------------------
-- inArray
--
-- Returns true if valueToFind is a member of the array, and false otherwise.
------------------------------------------------------------------------------------
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- if valueToFind is nil, error?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end
return p
085e7094ac84eb0132ee65822cf3f69cd8ba3d81
Module:String
828
74
142
2024-07-12T20:51:49Z
zhwp>Xiplus-abot
0
已保护“[[Module:String]]”:高風險模板:2398431引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
Scribunto
text/plain
--[[
This module is intended to provide access to basic string functions.
Most of the functions provided here can be invoked with named parameters,
unnamed parameters, or a mixture. If named parameters are used, Mediawiki will
automatically remove any leading or trailing whitespace from the parameter.
Depending on the intended use, it may be advantageous to either preserve or
remove such whitespace.
Global options
ignore_errors: If set to 'true' or 1, any error condition will result in
an empty string being returned rather than an error message.
error_category: If an error occurs, specifies the name of a category to
include with the error message. The default category is
[Category:Errors reported by Module String].
no_category: If set to 'true' or 1, no category will be added if an error
is generated.
Unit tests for this module are available at Module:String/tests.
]]
local str = {}
--[[
len
This function returns the length of the target string.
Usage:
{{#invoke:String|len|target_string|}}
OR
{{#invoke:String|len|s=target_string}}
Parameters
s: The string whose length to report
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.len( frame )
local new_args = str._getParameters( frame.args, {'s'} );
local s = new_args['s'] or '';
return mw.ustring.len( s )
end
--[[
sub
This function returns a substring of the target string at specified indices.
Usage:
{{#invoke:String|sub|target_string|start_index|end_index}}
OR
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}
Parameters
s: The string to return a subset of
i: The fist index of the substring to return, defaults to 1.
j: The last index of the string to return, defaults to the last character.
The first character of the string is assigned an index of 1. If either i or j
is a negative value, it is interpreted the same as selecting a character by
counting from the end of the string. Hence, a value of -1 is the same as
selecting the last character of the string.
If the requested indices are out of range for the given string, an error is
reported.
]]
function str.sub( frame )
local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } );
local s = new_args['s'] or '';
local i = tonumber( new_args['i'] ) or 1;
local j = tonumber( new_args['j'] ) or -1;
local len = mw.ustring.len( s );
-- Convert negatives for range checking
if i < 0 then
i = len + i + 1;
end
if j < 0 then
j = len + j + 1;
end
if i > len or j > len or i < 1 or j < 1 then
return str._error( '截取字符串索引脱离区间' );
end
if j < i then
return str._error( '截取字符串指示脱离顺序' );
end
return mw.ustring.sub( s, i, j )
end
--[[
This function implements that features of {{str sub old}} and is kept in order
to maintain these older templates.
]]
function str.sublength( frame )
local i = tonumber( frame.args.i ) or 0
local len = tonumber( frame.args.len )
return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )
end
--[[
match
This function returns a substring from the source string that matches a
specified pattern.
Usage:
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}
OR
{{#invoke:String|pos|s=source_string|pattern=pattern_string|start=start_index
|match=match_number|plain=plain_flag|nomatch=nomatch_output}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
start: The index within the source string to start the search. The first
character of the string has index 1. Defaults to 1.
match: In some cases it may be possible to make multiple matches on a single
string. This specifies which match to return, where the first match is
match= 1. If a negative number is specified then a match is returned
counting from the last match. Hence match = -1 is the same as requesting
the last match. Defaults to 1.
plain: A flag indicating that the pattern should be understood as plain
text. Defaults to false.
nomatch: If no match is found, output the "nomatch" value rather than an error.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from each string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
If the match_number or start_index are out of range for the string being queried, then
this function generates an error. An error is also generated if no match is found.
If one adds the parameter ignore_errors=true, then the error will be suppressed and
an empty string will be returned on any failure.
For information on constructing Lua patterns, a form of [regular expression], see:
* http://www.lua.org/manual/5.1/manual.html#5.4.1
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns
]]
function str.match( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} );
local s = new_args['s'] or '';
local start = tonumber( new_args['start'] ) or 1;
local plain_flag = str._getBoolean( new_args['plain'] or false );
local pattern = new_args['pattern'] or '';
local match_index = math.floor( tonumber(new_args['match']) or 1 );
local nomatch = new_args['nomatch'];
if s == '' then
return str._error( '目标字符串是空的' );
end
if pattern == '' then
return str._error( '模式字符串是空的' );
end
if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then
return str._error( '要求的起始点脱离区间' );
end
if match_index == 0 then
return str._error( '匹配索引脱离区间' );
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local result
if match_index == 1 then
-- Find first match is simple case
result = mw.ustring.match( s, pattern, start )
else
if start > 1 then
s = mw.ustring.sub( s, start );
end
local iterator = mw.ustring.gmatch(s, pattern);
if match_index > 0 then
-- Forward search
for w in iterator do
match_index = match_index - 1;
if match_index == 0 then
result = w;
break;
end
end
else
-- Reverse search
local result_table = {};
local count = 1;
for w in iterator do
result_table[count] = w;
count = count + 1;
end
result = result_table[ count + match_index ];
end
end
if result == nil then
if nomatch == nil then
return str._error( '找不到匹配' );
else
return nomatch;
end
else
return result;
end
end
--[[
pos
This function returns a single character from the target string at position pos.
Usage:
{{#invoke:String|pos|target_string|index_value}}
OR
{{#invoke:String|pos|target=target_string|pos=index_value}}
Parameters
target: The string to search
pos: The index for the character to return
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
The first character has an index value of 1.
If one requests a negative value, this function will select a character by counting backwards
from the end of the string. In other words pos = -1 is the same as asking for the last character.
A requested value of zero, or a value greater than the length of the string returns an error.
]]
function str.pos( frame )
local new_args = str._getParameters( frame.args, {'target', 'pos'} );
local target_str = new_args['target'] or '';
local pos = tonumber( new_args['pos'] ) or 0;
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
return str._error( '字符串索引脱离区间' );
end
return mw.ustring.sub( target_str, pos, pos );
end
--[[
str_find
This function duplicates the behavior of {{str_find}}, including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for
new code and templates. New code is recommended to use the "find" function instead.
Returns the first index in "source" that is a match to "target". Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".
Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.
]]
function str.str_find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target'} );
local source_str = new_args['source'] or '';
local target_str = new_args['target'] or '';
if target_str == '' then
return 1;
end
local start = mw.ustring.find( source_str, target_str, 1, true )
if start == nil then
start = -1
end
return start
end
--[[
find
This function allows one to search for a target string or pattern within another
string.
Usage:
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}
OR
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}
Parameters
source: The string to search
target: The string or pattern to find within source
start: The index within the source string to start the search, defaults to 1
plain: Boolean flag indicating that target should be understood as plain
text and not as a Lua style regular expression, defaults to true
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
This function returns the first index >= "start" where "target" can be found
within "source". Indices are 1-based. If "target" is not found, then this
function returns 0. If either "source" or "target" are missing / empty, this
function also returns 0.
This function should be safe for UTF-8 strings.
]]
function str.find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['target'] or '';
local start_pos = tonumber(new_args['start']) or 1;
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return 0;
end
plain = str._getBoolean( plain );
local start = mw.ustring.find( source_str, pattern, start_pos, plain )
if start == nil then
start = 0
end
return start
end
--[[
replace
This function allows one to replace a target string or pattern within another
string.
Usage:
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}
OR
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|
count=replacement_count|plain=plain_flag}}
Parameters
source: The string to search
pattern: The string or pattern to find within source
replace: The replacement text
count: The number of occurences to replace, defaults to all.
plain: Boolean flag indicating that pattern should be understood as plain
text and not as a Lua style regular expression, defaults to true
]]
function str.replace( frame )
local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['pattern'] or '';
local replace = new_args['replace'] or '';
local count = tonumber( new_args['count'] );
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return source_str;
end
plain = str._getBoolean( plain );
if plain then
pattern = str._escapePattern( pattern );
replace = mw.ustring.gsub( replace, "%%", "%%%%" ); --Only need to escape replacement sequences.
end
local result;
if count ~= nil then
result = mw.ustring.gsub( source_str, pattern, replace, count );
else
result = mw.ustring.gsub( source_str, pattern, replace );
end
return result;
end
--[[
simple function to pipe string.rep to templates.
]]
function str.rep( frame )
local repetitions = tonumber( frame.args[2] )
if not repetitions then
return str._error( 'function rep expects a number as second parameter, received "' .. ( frame.args[2] or '' ) .. '"' )
end
return string.rep( frame.args[1] or '', repetitions )
end
function str.split(inputstr, sep, no_pattern, ignore_null)
--#invoke 支援
if type(inputstr) == type({table}) then
if not getArgs then getArgs = require('Module:Arguments').getArgs end
args = getArgs(inputstr, {parentFirst=true})
for arg_name, arg_value in pairs( args ) do
if arg_name == 1 or arg_name == '1' or arg_name == "str" or arg_name == "inputstr" or arg_name == "input" then
input_str = arg_value
elseif arg_name == 2 or arg_name == '2' or arg_name == "sep" or arg_name == "separator" then
separ = arg_value
elseif arg_name == 3 or arg_name == '3' or arg_name == "no_pattern" or arg_name == "no pattern" then
no_pattern_flag = arg_value
elseif arg_name == 4 or arg_name == '4' or arg_name == "ignore_null" or arg_name == "ignore null" then
ignore_null_flag = arg_value
elseif arg_name == 5 or arg_name == '5' or arg_name == "format" then
format = arg_value or "*{{{1}}}\n";
end
end
if not yesno then yesno = require('Module:Yesno') end
no_pattern_flag = yesno( no_pattern_flag or 'yes' )
ignore_null_flag = yesno( ignore_null_flag or 'no' )
is_invoke = true
format = mw.ustring.gsub(format or "*{{{1}}}\n", "%{%{%{.-%}%}%}", "%%s" );
it = mw.ustring.find(format, "%%s", 1)
if it == nil then format = format .. "%s" end
format = mw.ustring.gsub(format, "\\n", "\n")
else
input_str = inputstr
separ = sep
no_pattern_flag = no_pattern
ignore_null_flag = ignore_null
is_invoke = false
end
input_str = input_str or ''
separ = separ or "%s"
if no_pattern_flag == nil then no_pattern_flag = true end
if ignore_null_flag == nil then ignore_null_flag = false end
length = mw.ustring.len(input_str)
--split函數起點
if no_pattern_flag then
separ = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(separ,
"%[", "%["), "%]", "%]"), "%{", "%{"), "%}", "%}"), "%%", "%%%%"), "%)", "%)"), "%-", "%-"),
"%^", "%^"), "%$", "%$"), "%(", "%("), "%.", "%."), "%*", "%*"), "%+", "%+"), "%|", "%|");
end
iterator = 1 ; i = 1 ; flag = true
result = {}
separ_str_begin, separ_str_end = mw.ustring.find(input_str, separ, iterator)
--
debug1 = 1
--
while flag do
debug1 = debug1 + 1
if separ_str_begin == nil or iterator > length or debug1 >= 100 then
separ_str_begin = 0
separ_str_end = -2
flag = false
end
if separ_str_end < separ_str_begin then separ_str_end = separ_str_begin end
finded_str = mw.ustring.sub(input_str, iterator, separ_str_begin - 1)
if not(mw.text.trim(finded_str) == '' and ignore_null_flag) then
result[i] = finded_str
i = i + 1
end
iterator = separ_str_end + 1
separ_str_begin, separ_str_end = mw.ustring.find(input_str, separ, iterator)
end
if is_invoke then
body = ''
for i, result_str in pairs( result ) do
body = body .. mw.ustring.gsub(format, "%%s", result_str)
end
return body
end
return result;
end
--[[
join
Join all non empty arguments together; the first argument is the separator.
Usage:
{{#invoke:String|join|sep|one|two|three}}
]]
function str.join(frame)
local args = {}
local sep
for _, v in ipairs( frame.args ) do
if sep then
if v ~= '' then
table.insert(args, v)
end
else
sep = v
end
end
return table.concat( args, sep or '' )
end
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function str._getParameters( frame_args, arg_list )
local new_args = {};
local index = 1;
local value;
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index];
index = index + 1;
end
new_args[arg] = value;
end
return new_args;
end
--[[
Helper function to handle error messages.
]]
function str._error( error_str )
local frame = mw.getCurrentFrame();
local error_category = frame.args.error_category or '字符串模块报告的错误';
local ignore_errors = frame.args.ignore_errors or false;
local no_category = frame.args.no_category or false;
if str._getBoolean(ignore_errors) then
return '';
end
local error_str = '<strong class="error">字符串模块出错:' .. error_str .. '</strong>';
if error_category ~= '' and not str._getBoolean( no_category ) then
error_str = '[[Category:' .. error_category .. ']]' .. error_str;
end
return error_str;
end
--[[
Helper Function to interpret boolean strings
]]
function str._getBoolean( boolean_str )
local boolean_value;
if type( boolean_str ) == 'string' then
boolean_str = boolean_str:lower();
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
or boolean_str == '' then
boolean_value = false;
else
boolean_value = true;
end
elseif type( boolean_str ) == 'boolean' then
boolean_value = boolean_str;
else
error( '布尔值找不到' );
end
return boolean_value
end
--[[
Helper function that escapes all pattern characters so that they will be treated
as plain text.
]]
function str._escapePattern( pattern_str )
return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end
return str
46d6ec0e303056a09a84a6da45fba79504276c7f
Module:List
828
86
166
2024-07-12T20:52:09Z
zhwp>Xiplus-abot
0
已保护“[[Module:List]]”:高風險模板:92024引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
-- This module outputs different kinds of lists. At the moment, bulleted,
-- unbulleted, horizontal, ordered, and horizontal ordered lists are supported.
local libUtil = require('libraryUtil')
local checkType = libUtil.checkType
local mTableTools = require('Module:TableTools')
local p = {}
local listTypes = {
['bulleted'] = true,
['unbulleted'] = true,
['horizontal'] = true,
['ordered'] = true,
['horizontal_ordered'] = true
}
function p.makeListData(listType, args)
-- Constructs a data table to be passed to p.renderList.
local data = {}
-- Classes
data.classes = {}
if listType == 'horizontal' or listType == 'horizontal_ordered' then
table.insert(data.classes, 'hlist')
elseif listType == 'unbulleted' then
table.insert(data.classes, 'plainlist')
end
table.insert(data.classes, args.class)
-- Main div style
data.style = args.style
-- Indent for horizontal lists
if listType == 'horizontal' or listType == 'horizontal_ordered' then
local indent = tonumber(args.indent)
indent = indent and indent * 1.6 or 0
if indent > 0 then
data.marginLeft = indent .. 'em'
end
end
-- List style types for ordered lists
-- This could be "1, 2, 3", "a, b, c", or a number of others. The list style
-- type is either set by the "type" attribute or the "list-style-type" CSS
-- property.
if listType == 'ordered' or listType == 'horizontal_ordered' then
data.listStyleType = args.list_style_type or args['list-style-type']
data.type = args['type']
-- Detect invalid type attributes and attempt to convert them to
-- list-style-type CSS properties.
if data.type
and not data.listStyleType
and not tostring(data.type):find('^%s*[1AaIi]%s*$')
then
data.listStyleType = data.type
data.type = nil
end
end
-- List tag type
if listType == 'ordered' or listType == 'horizontal_ordered' then
data.listTag = 'ol'
else
data.listTag = 'ul'
end
-- Start number for ordered lists
data.start = args.start
if listType == 'horizontal_ordered' then
-- Apply fix to get start numbers working with horizontal ordered lists.
local startNum = tonumber(data.start)
if startNum then
data.counterReset = 'listitem ' .. tostring(startNum - 1)
end
end
-- List style
-- ul_style and ol_style are included for backwards compatibility. No
-- distinction is made for ordered or unordered lists.
data.listStyle = args.list_style
-- List items
-- li_style is included for backwards compatibility. item_style was included
-- to be easier to understand for non-coders.
data.itemStyle = args.item_style or args.li_style
data.items = {}
for i, num in ipairs(mTableTools.numKeys(args)) do
local item = {}
item.content = args[num]
item.style = args['item' .. tostring(num) .. '_style']
or args['item_style' .. tostring(num)]
or args['li_style' .. tostring(num)]
item.value = args['item' .. tostring(num) .. '_value']
or args['item_value' .. tostring(num)]
or args['li_value' .. tostring(num)]
table.insert(data.items, item)
end
return data
end
function p.renderList(data)
-- Renders the list HTML.
-- Return the blank string if there are no list items.
if type(data.items) ~= 'table' or #data.items < 1 then
return ''
end
-- Render the main div tag.
local root = mw.html.create('div')
for i, class in ipairs(data.classes or {}) do
root:addClass(class)
end
root:css{['margin-left'] = data.marginLeft}
if data.style then
root:cssText(data.style)
end
-- Render the list tag.
local list = root:tag(data.listTag or 'ul')
list
:attr{start = data.start, type = data.type}
:css{
['counter-reset'] = data.counterReset,
['list-style-type'] = data.listStyleType
}
if data.listStyle then
list:cssText(data.listStyle)
end
-- Render the list items
for i, t in ipairs(data.items or {}) do
local item = list:tag('li')
if data.itemStyle then
item:cssText(data.itemStyle)
end
if t.style then
item:cssText(t.style)
end
item
:attr{value = t.value}
:wikitext(t.content)
end
return tostring(root)
end
function p.renderTrackingCategories(args)
local isDeprecated = false -- Tracks deprecated parameters.
for k, v in pairs(args) do
k = tostring(k)
if k:find('^item_style%d+$') or k:find('^item_value%d+$') then
isDeprecated = true
break
end
end
local ret = ''
if isDeprecated then
ret = ret .. '[[Category:含有过期参数的列表模板]]'
end
return ret
end
function p.makeList(listType, args)
if not listType or not listTypes[listType] then
error(string.format(
"bad argument #1 to 'makeList' ('%s'不是合适的列表类型)",
tostring(listType)
), 2)
end
checkType('makeList', 2, args, 'table')
local data = p.makeListData(listType, args)
local list = p.renderList(data)
local trackingCategories = p.renderTrackingCategories(args)
return list .. trackingCategories
end
for listType in pairs(listTypes) do
p[listType] = function (frame)
local mArguments = require('Module:Arguments')
local origArgs = mArguments.getArgs(frame)
-- Copy all the arguments to a new table, for faster indexing.
local args = {}
for k, v in pairs(origArgs) do
args[k] = v
end
return p.makeList(listType, args)
end
end
return p
4199cf5283d8a457f8e13ce703726cb8ea84a08b
Module:Documentation/config
828
98
190
2024-07-12T20:52:19Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation/config]]”:高風險模板:32591引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[那艺娜维基:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[那艺娜维基:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[那艺娜维基:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
c0991af7f04ef8f2b12d94f64d2e0ea5968d2413
264
190
2024-07-12T20:52:19Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation/config]]”:高風險模板:32591引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[那艺娜维基:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[那艺娜维基:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[那艺娜维基:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
c0991af7f04ef8f2b12d94f64d2e0ea5968d2413
382
264
2024-07-12T20:52:19Z
zhwp>Xiplus-abot
0
已保护“[[Module:Documentation/config]]”:高風險模板:32591引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[Wikipedia:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[Wikipedia:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[Wikipedia:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[Wikipedia:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[Wikipedia:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
a260fb140eb8c1da0379a83c239f77a97d7b5b1d
Template:Documentation subpage
10
101
196
2024-07-12T20:52:29Z
zhwp>Xiplus-abot
0
已保护“[[Template:Documentation subpage]]”:高風險模板:17434引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[那艺娜维基:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
a29fcace7b5ee767264d3f8874aa71d0eb6ec03d
270
196
2024-07-12T20:52:29Z
zhwp>Xiplus-abot
0
已保护“[[Template:Documentation subpage]]”:高風險模板:17434引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[那艺娜维基:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
a29fcace7b5ee767264d3f8874aa71d0eb6ec03d
388
270
2024-07-12T20:52:29Z
zhwp>Xiplus-abot
0
已保护“[[Template:Documentation subpage]]”:高風險模板:17434引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许模板编辑员](无限期)[移动=仅允许模板编辑员](无限期))
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[Wikipedia:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[Wikipedia:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[Wikipedia:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
9de15399959448e597a6d8b537d93465f02dba4e
Template:Lua
10
104
202
2024-07-12T20:52:39Z
zhwp>Xiplus-abot
0
已保护“[[Template:Lua]]”:高風險模板:2871引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
wikitext
text/x-wiki
#重定向 [[Template:Uses Lua]]
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
{{模板捷徑重定向}}
}}
c08eca5e48152ab4733cd1afe7dc46252e4402e3
Module:Lua banner
828
108
210
2024-07-12T20:52:49Z
zhwp>Xiplus-abot
0
已保护“[[Module:Lua banner]]”:高風險模板:2966引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[那艺娜维基:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
dc0cc1f5c839b737e09cd1889b2121194b550c65
272
210
2024-07-12T20:52:49Z
zhwp>Xiplus-abot
0
已保护“[[Module:Lua banner]]”:高風險模板:2966引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[那艺娜维基:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
dc0cc1f5c839b737e09cd1889b2121194b550c65
572
272
2024-07-12T20:52:49Z
zhwp>Xiplus-abot
0
已保护“[[Module:Lua banner]]”:高風險模板:2966引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许自动确认用户](无限期)[移动=仅允许自动确认用户](无限期))
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[Wikipedia:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
ed205902af06accc81ba0b34ccb6dca977620306
MediaWiki:Gadget-twinklexfd.js
8
158
318
2024-07-13T05:27:32Z
zhwp>Xiplus
0
Repo at 0aa6125: Preload recently used batch reason
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklexfd.js: XFD module
****************************************
* Mode of invocation: Tab ("XFD")
* Active on: Existing, non-special pages, except for file pages with no local (non-Commons) file which are not redirects
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.xfd = function twinklexfd() {
// Disable on:
// * special pages
// * Flow pages
// * non-existent pages
// * files on Commons, whether there is a local page or not (unneeded local pages of files on Commons are eligible for CSD F2)
// * file pages without actual files (these are eligible for CSD G8)
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && (document.getElementById('mw-sharedupload') || (!document.getElementById('mw-imagepage-section-filehistory') && !Morebits.isPageRedirect())))) {
return;
}
Twinkle.addPortletLink(Twinkle.xfd.callback, conv({ hans: '提删', hant: '提刪' }), 'tw-xfd', conv({ hans: '提交删除讨论', hant: '提交刪除討論' }));
};
Twinkle.xfd.currentRationale = null;
// error callback on Morebits.status.object
Twinkle.xfd.printRationale = function twinklexfdPrintRationale() {
if (Twinkle.xfd.currentRationale) {
Morebits.status.printUserText(Twinkle.xfd.currentRationale, conv({ hans: '您的理由已在下方提供,如果您想重新提交,请将其复制到一新窗口中:', hant: '您的理由已在下方提供,如果您想重新提交,請將其複製到一新視窗中:' }));
// only need to print the rationale once
Twinkle.xfd.currentRationale = null;
}
};
Twinkle.xfd.callback = function twinklexfdCallback() {
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '提交存废讨论', hant: '提交存廢討論' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '关于存废讨论', hant: '關於存廢討論' }), 'WP:XFD');
Window.addFooterLink(conv({ hans: '提删设置', hant: '提刪設定' }), 'WP:TW/PREF#xfd');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#xfd');
var form = new Morebits.quickForm(Twinkle.xfd.callback.evaluate);
var categories = form.append({
type: 'select',
name: 'category',
label: conv({ hans: '提交类型:', hant: '提交類別:' }),
event: Twinkle.xfd.callback.change_category
});
categories.append({
type: 'option',
label: conv({ hans: '页面存废讨论', hant: '頁面存廢討論' }),
selected: mw.config.get('wgNamespaceNumber') === 0, // Main namespace
value: 'afd'
});
categories.append({
type: 'option',
label: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' }),
selected: mw.config.get('wgNamespaceNumber') === 6, // File namespace
value: 'ffd'
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,通知页面创建者', hant: '如可能,通知頁面建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '在页面创建者讨论页上放置一通知模板。', hant: '在頁面建立者討論頁上放置一通知模板。' }),
checked: true
}
]
}
);
form.append({
type: 'field',
label: '工作区',
name: 'work_area'
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
if (mw.config.get('wgPageContentModel') !== 'wikitext') {
form = new Morebits.quickForm(Twinkle.xfd.callback.evaluate);
form.append({
type: 'div',
label: [
conv({ hans: 'Twinkle不支持在页面内容模型为', hant: 'Twinkle不支援在頁面內容模型為' }),
mw.config.get('wgPageContentModel'),
conv({ hans: '的页面上挂上存废讨论模板,请参见', hant: '的頁面上掛上存廢討論模板,請參見' }),
$('<a>').attr({ target: '_blank', href: mw.util.getUrl('WP:SPECIALSD') }).text(conv({ hans: '手动放置模板时的注意事项', hant: '手動放置模板時的注意事項' }))[0],
'。'
]
});
Window.setContent(form.render());
Window.display();
return;
}
// We must init the controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.category.dispatchEvent(evt);
};
Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory(e) {
var value = e.target.value;
var form = e.target.form;
var old_area = Morebits.quickForm.getElements(e.target.form, 'work_area')[0];
var work_area = null;
var oldreasontextbox = form.getElementsByTagName('textarea')[0];
var oldreason = oldreasontextbox ? oldreasontextbox.value : '';
var appendReasonBox = function twinklexfdAppendReasonBox(xfd_cat) {
switch (xfd_cat) {
case 'fwdcsd':
oldreason = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
break;
case 'fame':
oldreason = Twinkle.getPref('afdFameDefaultReason');
break;
case 'substub':
oldreason = Twinkle.getPref('afdSubstubDefaultReason');
break;
default:
break;
}
work_area.append({
type: 'textarea',
name: 'xfdreason',
label: conv({ hans: '提删理由:', hant: '提刪理由:' }),
value: oldreason,
tooltip: conv({ hans: '您可以使用维基格式,Twinkle将自动为您加入签名。如果您使用批量提删功能,存废讨论页只会使用第一次提交的理由,但之后您仍需提供以用于删除通告模板的参数。', hant: '您可以使用維基格式,Twinkle將自動為您加入簽名。如果您使用批次提刪功能,存廢討論頁只會使用第一次提交的理由,但之後您仍需提供以用於刪除通告模板的參數。' }),
placeholder: conv({ hans: '此值亦显示于页面的删除通告模板内,故务必提供此值,避免使用“同上”等用语。', hant: '此值亦顯示於頁面的刪除通告模板內,故務必提供此值,避免使用「同上」等用語。' })
});
// TODO possible future "preview" link here
};
switch (value) {
case 'afd':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '页面存废讨论', hant: '頁面存廢討論' }),
name: 'work_area'
});
work_area.append({
type: 'checkbox',
list: [
{
label: '使用<noinclude>包裹模板',
value: 'noinclude',
name: 'noinclude',
checked: mw.config.get('wgNamespaceNumber') === 10, // Template namespace
tooltip: conv({ hans: '使其不会在被包含时出现。', hant: '使其不會在被包含時出現。' })
}
]
});
var afd_category = work_area.append({
type: 'select',
name: 'xfdcat',
label: conv({ hans: '选择提删类型:', hant: '選擇提刪類別:' }),
event: Twinkle.xfd.callback.change_afd_category
});
var afd_cat = 'delete';
if (Twinkle.getPref('afdDefaultCategory') === 'same') {
if (localStorage.Twinkle_afdCategory === undefined) {
localStorage.Twinkle_afdCategory = 'delete';
} else {
afd_cat = localStorage.Twinkle_afdCategory;
}
}
afd_category.append({ type: 'option', label: conv({ hans: '删除', hant: '刪除' }), value: 'delete', selected: afd_cat === 'delete' });
afd_category.append({ type: 'option', label: conv({ hans: '合并', hant: '合併' }), value: 'merge', selected: afd_cat === 'merge' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基词典', hant: '移動到維基詞典' }), value: 'vmd', selected: afd_cat === 'vmd' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基文库', hant: '移動到維基文庫' }), value: 'vms', selected: afd_cat === 'vms' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' }), value: 'vmb', selected: afd_cat === 'vmb' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基语录', hant: '移動到維基語錄' }), value: 'vmq', selected: afd_cat === 'vmq' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基导游', hant: '移動到維基導遊' }), value: 'vmvoy', selected: afd_cat === 'vmvoy' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基学院', hant: '移動到維基學院' }), value: 'vmv', selected: afd_cat === 'vmv' });
if (Twinkle.getPref('FwdCsdToXfd')) {
afd_category.append({ type: 'option', label: conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' }), value: 'fwdcsd', selected: afd_cat === 'fwdcsd' });
}
afd_category.append({ type: 'option', label: conv({ hans: '批量关注度提删', hant: '批次關注度提刪' }), value: 'fame', selected: afd_cat === 'fame' });
afd_category.append({ type: 'option', label: conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' }), value: 'substub', selected: afd_cat === 'substub' });
afd_category.append({ type: 'option', label: conv({ hans: '批量其他提删', hant: '批次其他提刪' }), value: 'batch', selected: afd_cat === 'batch' });
work_area.append({
type: 'input',
name: 'mergeinto',
label: conv({ hans: '合并到:', hant: '合併到:' }),
hidden: true
});
appendReasonBox(afd_cat);
work_area.append({
type: 'textarea',
name: 'fwdcsdreason',
label: conv({ hans: '转交理由:', hant: '轉交理由:' }),
tooltip: conv({ hans: '您可以使用维基格式,Twinkle将自动为您加入签名。', hant: '您可以使用維基格式,Twinkle將自動為您加入簽名。' }),
hidden: true
});
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
form.xfdcat.dispatchEvent(evt);
break;
case 'ffd':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' }),
name: 'work_area'
});
appendReasonBox('ffd');
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
default:
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '未定义', hant: '未定義' }),
name: 'work_area'
});
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
}
// Return to checked state when switching
form.notify.checked = true;
form.notify.disabled = false;
};
Twinkle.xfd.getAfdBatchReason = function twinklexfdGetAfdBatchReason() {
var previousTime = parseInt(localStorage.getItem('Twinkle_afdBatchReasonTime'));
if (previousTime && new Date() - new Date(previousTime) < 1000 * 60 * 60) {
return localStorage.getItem('Twinkle_afdBatchReasonText') || '';
}
return '';
};
Twinkle.xfd.callback.change_afd_category = function twinklexfdCallbackChangeAfdCategory(e) {
if (e.target.value === 'merge') {
e.target.form.mergeinto.parentElement.removeAttribute('hidden');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.mergeinto.previousElementSibling.innerHTML = conv({ hans: '合并到:', hant: '合併到:' });
} else if (e.target.value === 'fwdcsd') {
e.target.form.mergeinto.parentElement.removeAttribute('hidden');
e.target.form.fwdcsdreason.parentElement.removeAttribute('hidden');
e.target.form.mergeinto.previousElementSibling.innerHTML = '提交人:';
e.target.form.xfdreason.value = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
} else if (e.target.value === 'fame') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.getPref('afdFameDefaultReason');
} else if (e.target.value === 'substub') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.getPref('afdSubstubDefaultReason');
} else if (e.target.value === 'batch') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.xfd.getAfdBatchReason();
} else {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
}
if (Twinkle.getPref('afdDefaultCategory') === 'same') {
localStorage.Twinkle_afdCategory = e.target.value;
}
};
Twinkle.xfd.callbacks = {
afd: {
main: function(tagging_page) {
var params = tagging_page.getCallbackParameters();
Twinkle.xfd.callbacks.afd.taggingArticle(tagging_page);
// Adding discussion
var discussion_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入讨论到当日列表', hant: '加入討論到當日列表' }));
discussion_page.setFollowRedirect(true);
discussion_page.setCallbackParameters(params);
discussion_page.load(Twinkle.xfd.callbacks.afd.todaysList);
// Notification to first contributor
if (params.notify) {
// Disallow warning yourself
if (params.creator === mw.config.get('wgUserName')) {
Morebits.status.warn(conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')', conv({ hans: '您创建了该页,跳过通知', hant: '您建立了該頁,跳過通知' }));
params.creator = null;
} else {
var talkPageName = 'User talk:' + params.creator;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
flowpage.setTopic('页面[[:' + Morebits.pageNameNorm + ']]存废讨论通知');
flowpage.setContent('{{subst:AFDNote|' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
var notifytext = '\n{{subst:AFDNote|' + Morebits.pageNameNorm + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary('通知:页面[[' + Morebits.pageNameNorm + ']]存废讨论提名');
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('xfdWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, params.creator);
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, null);
}
},
taggingArticle: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var tag = '{{vfd|' + Morebits.string.formatReasonText(params.xfdreason);
switch (params.xfdcat) {
case 'vmd':
tag += '|wikt';
break;
case 'vms':
tag += '|s';
break;
case 'vmb':
tag += '|b';
break;
case 'vmq':
tag += '|q';
break;
case 'vmvoy':
tag += '|voy';
break;
case 'vmv':
tag += '|v';
break;
default:
break;
}
if (Morebits.isPageRedirect()) {
tag += '|r';
}
tag += '|date={{subst:#time:Y/m/d}}}}';
if (params.noinclude) {
tag = '<noinclude>' + tag + '</noinclude>';
// 只有表格需要单独加回车,其他情况加回车会破坏模板。
if (text.indexOf('{|') === 0) {
tag += '\n';
}
} else {
tag += '\n';
}
// Then, test if there are speedy deletion-related templates on the article.
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|(?:hang|hold)[- ]?on)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && confirm(conv({ hans: '在页面上找到快速删除模板,要移除吗?', hant: '在頁面上找到快速刪除模板,要移除嗎?' }))) {
text = textNoSd;
}
var textNoNotMandarin = text.replace(/\{\{\s*(NotMandarin|Notchinese|非中文|非現代漢語|非现代汉语|非現代標準漢語|非现代标准汉语)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoNotMandarin && confirm(conv({ hans: '在页面上找到非现代标准汉语模板,要移除吗?', hant: '在頁面上找到非現代標準漢語模板,要移除嗎?' }))) {
text = textNoNotMandarin;
}
var textNoAfc = text.replace(/{{\s*AFC submission\s*\|\s*\|[^}]*?}}\s*/ig, '');
if (text !== textNoAfc && confirm(conv({ hans: '在页面上找到AFC提交模板,要移除吗?', hant: '在頁面上找到AFC提交模板,要移除嗎?' }))) {
text = textNoAfc;
}
// Mark the page as patrolled, if wanted
if (Twinkle.getPref('markXfdPagesAsPatrolled')) {
pageobj.patrol();
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '页面存废讨论:[[', hant: '頁面存廢討論:[[' }) + params.logpage + '#' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchPage'));
pageobj.save();
},
todaysList: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var type = '';
var to = '';
switch (params.xfdcat) {
case 'vmd':
case 'vms':
case 'vmb':
case 'vmq':
case 'vmvoy':
case 'vmv':
type = 'vm';
to = params.xfdcat;
break;
case 'fwdcsd':
case 'merge':
to = params.mergeinto;
/* Fall through */
default:
type = params.xfdcat;
break;
}
var append = true;
switch (type) {
case 'fame':
case 'substub':
case 'batch':
var commentText = '<!-- Twinkle: User:' + mw.config.get('wgUserName') + ' 的 ' + type + ' 提刪插入點,請勿變更或移除此行,除非不再於此頁提刪 -->';
var newText = '===[[:' + Morebits.pageNameNorm + ']]===';
if (type === 'fame') {
newText += '\n{{Findsources|' + Morebits.pageNameNorm + '}}';
}
if (text.indexOf(commentText) !== -1) {
text = text.replace(commentText, newText + '\n\n' + commentText);
pageobj.setPageText(text);
append = false;
} else {
var appendText = '\n{{safesubst:SafeAfdHead}}\n' +
{
fame: '==30天后仍掛有{{tl|notability}}模板的條目==\n' +
'<span style="font-size:smaller;">(已掛[[template:notability|關注度模板]]30天)</span>',
substub: '==到期篩選的小小作品==',
batch: '==批量提刪=='
}[type] + '\n' +
newText + '\n\n' +
commentText + '\n' +
'----\n' +
':{{删除}}理據:' + Morebits.string.formatReasonText(params.xfdreason) + '\n' +
'提报以上' + {
fame: '<u>关注度不足</u>条目',
substub: '<u>小小作品</u>',
batch: '頁面'
}[type] + '的維基人及時間:<br id="no-new-title" />~~~~';
pageobj.setAppendText(appendText);
}
break;
default:
pageobj.setAppendText('\n{{subst:DRItem|Type=' + type + '|DRarticles=' + Morebits.pageNameNorm + '|Reason=' + Morebits.string.formatReasonText(params.xfdreason) + (params.fwdcsdreason.trim() !== '' ? '<br>\n轉交理由:' + params.fwdcsdreason : '') + '|To=' + to + '}}~~~~');
break;
}
pageobj.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ 新提案');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchDiscussion'));
pageobj.setCreateOption('recreate');
if (append) {
pageobj.append();
} else {
pageobj.save();
}
Twinkle.xfd.currentRationale = null; // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
},
lookupCreation: function (target_page) {
target_page.getStatusElement().info('完成');
var params = target_page.getCallbackParameters();
params.creator = target_page.getCreator();
// Tagging page
var tagging_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入存废讨论模板到页面', hant: '加入存廢討論模板到頁面' }));
tagging_page.setFollowRedirect(false);
tagging_page.setCallbackParameters(params);
tagging_page.load(Twinkle.xfd.callbacks.afd.tryTagging);
},
tryTagging: function (tagging_page) {
var statelem = tagging_page.getStatusElement();
// defaults to /doc for lua modules, which may not exist
if (!tagging_page.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = tagging_page.getPageText();
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想继续提报?', hant: '}}已被置於頁面中,您是否仍想繼續提報?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
var copyvio = /(?:\{\{\s*(copyvio)[^{}]*?\}\})/i.exec(text);
if (copyvio) {
statelem.error(conv({ hans: '页面中已有著作权验证模板。', hant: '頁面中已有著作權驗證模板。' }));
return;
}
Twinkle.xfd.callbacks.afd.main(tagging_page);
}
},
ffd: {
main: function(tagging_page) {
var params = tagging_page.getCallbackParameters();
Twinkle.xfd.callbacks.ffd.taggingImage(tagging_page);
// Adding discussion
var wikipedia_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入讨论到当日列表', hant: '加入討論到當日列表' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.xfd.callbacks.ffd.todaysList);
// Notification to first contributor
if (params.notify) {
// Disallow warning yourself
if (params.creator === mw.config.get('wgUserName')) {
Morebits.status.warn(conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')', conv({ hans: '您创建了该页,跳过通知', hant: '您建立了該頁,跳過通知' }));
return;
}
var talkPageName = 'User talk:' + params.creator;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
flowpage.setTopic('文件[[:File:' + mw.config.get('wgTitle') + ']]存废讨论通知');
flowpage.setContent('{{subst:idw|File:' + mw.config.get('wgTitle') + '|flow=yes}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
var notifytext = '\n{{subst:idw|File:' + mw.config.get('wgTitle') + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary('通知:文件[[' + Morebits.pageNameNorm + ']]存废讨论提名');
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('xfdWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, params.creator);
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, null);
}
},
taggingImage: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
pageobj.setPageText('{{ifd|' + Morebits.string.formatReasonText(params.xfdreason) + '|date={{subst:#time:Y/m/d}}}}\n' + text);
pageobj.setEditSummary(conv({ hans: '文件存废讨论:[[', hant: '檔案存廢討論:[[' }) + params.logpage + '#' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchPage'));
pageobj.setCreateOption('recreate'); // it might be possible for a file to exist without a description page
pageobj.save();
},
todaysList: function(pageobj) {
// var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
pageobj.setAppendText('\n{{subst:IfdItem|Filename=' + mw.config.get('wgTitle') + '|Uploader=' + params.creator + '|Reason=' + Morebits.string.formatReasonText(params.xfdreason) + '}}--~~~~');
pageobj.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ 新提案');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchDiscussion'));
pageobj.setCreateOption('recreate');
pageobj.append(function() {
Twinkle.xfd.currentRationale = null; // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
});
},
lookupCreation: function (target_page) {
target_page.getStatusElement().info('完成');
var params = target_page.getCallbackParameters();
params.creator = target_page.getCreator();
// Tagging file
var tagging_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入存废讨论模板到文件描述页', hant: '加入存廢討論模板到檔案描述頁' }));
tagging_page.setFollowRedirect(false);
tagging_page.setCallbackParameters(params);
tagging_page.load(Twinkle.xfd.callbacks.ffd.tryTagging);
},
tryTagging: function (tagging_page) {
var statelem = tagging_page.getStatusElement();
if (!tagging_page.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = tagging_page.getPageText();
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想继续提报?', hant: '}}已被置於頁面中,您是否仍想繼續提報?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
Twinkle.xfd.callbacks.ffd.main(tagging_page);
}
},
addToLog: function(params, initialContrib) {
var editsummary = conv({ hans: '记录对[[', hant: '記錄對[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的存废讨论提名', hant: ']]的存廢討論提名' });
var usl = new Morebits.userspaceLogger(Twinkle.getPref('xfdLogPageName'));
usl.initialText =
conv({
hans: '这是该用户使用[[WP:TW|Twinkle]]的提删模块做出的[[WP:XFD|存废讨论]]提名列表。\n\n' +
'如果您不再想保留此日志,请在[[' + Twinkle.getPref('configPage') + '|参数设置]]中关掉,并' +
'使用[[WP:CSD#O1|CSD O1]]提交快速删除。',
hant: '這是該使用者使用[[WP:TW|Twinkle]]的提刪模塊做出的[[WP:XFD|存廢討論]]提名列表。\n\n' +
'如果您不再想保留此日誌,請在[[' + Twinkle.getPref('configPage') + '|偏好設定]]中關掉,並' +
'使用[[WP:CSD#O1|CSD O1]]提交快速刪除。'
});
var xfdCatName;
switch (params.xfdcat) {
case 'delete':
xfdCatName = conv({ hans: '删除', hant: '刪除' });
break;
case 'merge':
xfdCatName = conv({ hans: '合并到', hant: '合併到' });
break;
case 'vmd':
xfdCatName = conv({ hans: '移动到维基词典', hant: '移動到維基詞典' });
break;
case 'vms':
xfdCatName = conv({ hans: '移动到维基文库', hant: '移動到維基文庫' });
break;
case 'vmb':
xfdCatName = conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' });
break;
case 'vmq':
xfdCatName = conv({ hans: '移动到维基语录', hant: '移動到維基語錄' });
break;
case 'vmvoy':
xfdCatName = conv({ hans: '移动到维基导游', hant: '移動到維基導遊' });
break;
case 'vmv':
xfdCatName = conv({ hans: '移动到维基学院', hant: '移動到維基學院' });
break;
case 'fwdcsd':
xfdCatName = conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' });
break;
case 'fame':
xfdCatName = conv({ hans: '批量关注度提删', hant: '批次關注度提刪' });
break;
case 'substub':
xfdCatName = conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' });
break;
case 'batch':
xfdCatName = conv({ hans: '批量其他提删', hant: '批次其他提刪' });
break;
default:
xfdCatName = conv({ hans: '文件存废讨论', hant: '檔案存廢討論' });
break;
}
// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
var appendText = '# [[:' + Morebits.pageNameNorm + ']]';
if (mw.config.get('wgNamespaceNumber') === 6) {
appendText += '([{{fullurl:Special:Log|page=' + mw.util.wikiUrlencode(mw.config.get('wgPageName')) + '}} ' + conv({ hans: '日志', hant: '日誌' }) + '])';
}
appendText += ':' + xfdCatName;
if (params.xfdcat === 'merge') {
appendText += '[[:' + params.mergeinto + ']]';
}
appendText += '。';
if (params.xfdreason) {
appendText += "'''" + (params.xfdcat === 'fwdcsd' ? conv({ hans: '原删除理据', hant: '原刪除理據' }) : conv({ hans: '理据', hant: '理據' })) + "''':" + Morebits.string.formatReasonForLog(params.xfdreason);
appendText = Morebits.string.appendPunctuation(appendText);
}
if (params.fwdcsdreason) {
appendText += "'''" + (params.xfdcat === 'fwdcsd' ? conv({ hans: '转交理据', hant: '轉交理據' }) : conv({ hans: '理据', hant: '理據' })) + "''':" + Morebits.string.formatReasonForLog(params.fwdcsdreason);
appendText = Morebits.string.appendPunctuation(appendText);
}
if (initialContrib) {
appendText += ';通知{{user|' + initialContrib + '}}';
}
appendText += ' ~~~~~\n';
usl.changeTags = Twinkle.changeTags;
usl.log(appendText, editsummary);
}
};
Twinkle.xfd.callback.evaluate = function(e) {
var params = Morebits.quickForm.getInputData(e.target);
if (params.xfdcat === 'merge' && params.mergeinto.trim() === '') {
alert(conv({ hans: '请提供合并目标!', hant: '請提供合併目標!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Twinkle.xfd.currentRationale = params.xfdreason;
Morebits.status.onError(Twinkle.xfd.printRationale);
if (!params.category) {
Morebits.status.error('错误', '未定义的动作');
return;
}
var target_page;
var date = new Morebits.date(); // XXX: avoid use of client clock, still used by TfD, FfD and CfD
switch (params.category) {
case 'afd': // AFD
if (params.xfdcat === 'batch') {
localStorage.setItem('Twinkle_afdBatchReasonText', params.xfdreason || '');
localStorage.setItem('Twinkle_afdBatchReasonTime', new Date().getTime());
}
params.logpage = 'Wikipedia:頁面存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc');
params.lognomination = Twinkle.getPref('logXfdNominations') && Twinkle.getPref('noLogOnXfdNomination').indexOf(params.xfdcat) === -1;
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = params.logpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
// Lookup creation
target_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '获取页面创建信息', hant: '取得頁面建立資訊' }));
target_page.setCallbackParameters(params);
if (mw.config.get('wgPageContentModel') === 'wikitext') {
target_page.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
}
target_page.lookupCreation(Twinkle.xfd.callbacks.afd.lookupCreation);
Morebits.wiki.removeCheckpoint();
break;
case 'ffd': // FFD
params.logpage = 'Wikipedia:檔案存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc');
params.lognomination = Twinkle.getPref('logXfdNominations') && Twinkle.getPref('noLogOnXfdNomination').indexOf('ffd') === -1;
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = params.logpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
// Lookup creation
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '获取页面创建信息', hant: '取得頁面建立資訊' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
wikipedia_page.lookupCreation(Twinkle.xfd.callbacks.ffd.lookupCreation);
Morebits.wiki.removeCheckpoint();
break;
default:
alert('twinklexfd:未定义的类别');
break;
}
};
Twinkle.addInitCallback(Twinkle.xfd, 'xfd');
})(jQuery);
// </nowiki>
99738e5e0724b0c6617ef148941f7cb54a389647
Template:每日一句
10
305
635
2024-07-13T13:48:58Z
zhwp>Manchiu
0
回退[[Special:Contributions/180.139.83.107|180.139.83.107]]([[User talk:180.139.83.107|对话]])的编辑,改回[[Special:Contributions/Minorax|Minorax]]的最后一个版本
wikitext
text/x-wiki
<div class="boilerplate metadata" align="center" style="border-top: 2px solid #3030FF; margin: 0 0 1em 0; border-bottom: 2px solid #3030FF; border-right: 2px solid #3030FF; margin: 0 0 1em 0; border-left: 2px solid #3030FF; padding: 5px 5px 5px 5px">
'''每日一句'''
<div style="max-height:240px;overflow:auto">
{{#invoke:Rand|randitem|{{每日一句/投稿}}}}</div><div class="center><span style="font-size:small;"><span class="mw-ui-button";style="text-color:white"><span class="plainlinks">{{purge|換一個}}</span></span> <span class="mw-ui-button";style="text-color:white">[[Template:每日一句/投稿|說一句]]</span></span></div></div><noinclude>
{{doc}}
[[Category:用戶頁模板|O]]
[[Category:維基百科幽默模板]]
</noinclude>
31728191bff7e1db5157e1b4bd2a8c68858c82ad
Template:Fix
10
270
562
2024-07-14T20:50:27Z
zhwp>Xiplus-abot
0
已更改“[[Template:Fix]]”的保护设置:高風險模板:100067引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
{{#switch:{{{subst|¬}}}
|¬={{category handler
|template=[[Category:需要检查替代引用的模板]]
|nocat={{{nocat|<noinclude>true</noinclude>}}}
}}
|SUBST=[[Category:錯誤使用替換引用的頁面]]
}}{{Category handler
|main={{Fix/category
|cat-date={{{cat-date|}}}
|cat={{{cat|}}}
|cat-date2={{{cat-date2|}}}
|cat2={{{cat2|}}}
|cat-date3={{{cat-date3|}}}
|cat3={{{cat3|}}}
|date={{{date|}}}
}}
|template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:包含缺少日期的清理标记的模板]]}}}}}}
|subpage=no
}}{{#if:{{{text|}}}
|<sup class="noprint Inline-Template {{{class|}}}" style="white-space:nowrap;">[{{#if:{{{pre-text|}}}
|{{{pre-text}}}
}}[[{{{link|Wikipedia:清理}}}|<span title="{{#if:{{{date|}}}|自{{{date}}}}}{{{title|{{{link|需要清理}}}}}}">{{{text|}}}</span>]]{{#if:{{{post-text|}}}
|{{{post-text}}}
}}]</sup>|{{{special|}}}
}}<noinclude>
{{Documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
93c3a5ef6bac7207480de71b0a2d1e25fc466a13
Module:Rand
828
323
671
2024-07-15T13:59:04Z
zhwp>Yoyolin0409
0
Scribunto
text/plain
local func = {}
function func.randitem( frame )
local text = frame.args[1]
local list = mw.text.split(text, frame.args[2] or '[\n\r]%s*%*%s*')
math.randomseed(os.time())
local n = #list
local r = 0
if mw.text.trim(list[1]) == '' then
r = math.random(n - 1) + 1
else
r = math.random(n)
end
return mw.text.trim(list[r])
end
return func
0dae3ba1a3f32ddedce6ff88c3016f05a583abf5
Module:Message box
828
59
112
2024-07-16T08:50:20Z
zhwp>Shizhao
0
[[mw:Help:Lint_errors/misc-tidy-replacement-issues]]
Scribunto
text/plain
-- This is a meta-module for producing message box templates, including {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.
-- Require necessary modules.
local getArgs = require('Module:Arguments').getArgs
local categoryHandler = require('Module:Category handler').main
local yesno = require('Module:Yesno')
-- Load the configuration page.
local cfgTables = mw.loadData('Module:Message box/configuration')
-- Get a language object for formatDate and ucfirst.
local lang = mw.language.getContentLanguage()
-- Set aliases for often-used functions to reduce table lookups.
local format = mw.ustring.format
local tinsert = table.insert
local tconcat = table.concat
local trim = mw.text.trim
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitleObject(page, ...)
if type(page) == 'string' then
-- Get the title object, passing the function through pcall
-- in case we are over the expensive function count limit.
local success, title = pcall(mw.title.new, page, ...)
if success then
return title
end
end
end
local function union(t1, t2)
-- Returns the union of two arrays.
local vals = {}
for i, v in ipairs(t1) do
vals[v] = true
end
for i, v in ipairs(t2) do
vals[v] = true
end
local ret = {}
for k in pairs(vals) do
tinsert(ret, k)
end
table.sort(ret)
return ret
end
local function getArgNums(args, prefix)
local nums = {}
for k, v in pairs(args) do
local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')
if num then
tinsert(nums, tonumber(num))
end
end
table.sort(nums)
return nums
end
--------------------------------------------------------------------------------
-- Box class definition
--------------------------------------------------------------------------------
local box = {}
box.__index = box
function box.new()
local obj = {}
setmetatable(obj, box)
return obj
end
function box.getNamespaceId(ns)
if not ns then return end
if type(ns) == 'string' then
ns = lang:ucfirst(mw.ustring.lower(ns))
if ns == 'Main' then
ns = 0
end
end
local nsTable = mw.site.namespaces[ns]
if nsTable then
return nsTable.id
end
end
function box.getMboxType(nsid)
-- Gets the mbox type from a namespace number.
if nsid == 0 then
return 'ambox' -- main namespace
elseif nsid == 6 then
return 'imbox' -- file namespace
elseif nsid == 14 then
return 'cmbox' -- category namespace
else
local nsTable = mw.site.namespaces[nsid]
if nsTable and nsTable.isTalk then
return 'tmbox' -- any talk namespace
else
return 'ombox' -- other namespaces or invalid input
end
end
end
function box:addCat(ns, cat, sort)
if type(cat) ~= 'string' then return end
local nsVals = {'main', 'template', 'all'}
local tname
for i, val in ipairs(nsVals) do
if ns == val then
tname = ns .. 'Cats'
end
end
if not tname then
for i, val in ipairs(nsVals) do
nsVals[i] = format('"%s"', val)
end
error('無效的ns參數傳送到box:addCat;有效的數值為' .. mw.text.listToText(nsVals, '、', '或'))
end
self[tname] = self[tname] or {}
if type(sort) == 'string' then
tinsert(self[tname], format('[[Category:%s|%s]]', cat, sort))
else
tinsert(self[tname], format('[[Category:%s]]', cat))
end
end
function box:addClass(class)
if type(class) ~= 'string' then return end
self.classes = self.classes or {}
tinsert(self.classes, class)
end
function box:setTitle(args)
-- Get the title object and the namespace.
self.pageTitle = getTitleObject(args.page ~= '' and args.page)
self.title = self.pageTitle or mw.title.getCurrentTitle()
self.demospace = args.demospace ~= '' and args.demospace or nil
self.nsid = box.getNamespaceId(self.demospace) or self.title.namespace
end
function box:getConfig(boxType)
-- Get the box config data from the data page.
if boxType == 'mbox' then
boxType = box.getMboxType(self.nsid)
end
local cfg = cfgTables[boxType]
if not cfg then
local boxTypes = {}
for k, v in pairs(dataTables) do
tinsert(boxTypes, format('"%s"', k))
end
tinsert(boxTypes, '"mbox"')
error(format('無效的訊息框類型「%s」;有效的類型為%s', tostring(boxType), mw.text.listToText(boxTypes)), 2)
end
return cfg
end
function box:removeBlankArgs(cfg, args)
-- Only allow blank arguments for the parameter names listed in cfg.allowBlankParams.
local newArgs = {}
for k, v in pairs(args) do
if v ~= '' then
newArgs[k] = v
end
end
for i, param in ipairs(cfg.allowBlankParams or {}) do
newArgs[param] = args[param]
end
return newArgs
end
function box:setBoxParameters(cfg, args)
-- Get type data.
self.type = args.type
local typeData = cfg.types[self.type]
self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData and true or false
typeData = typeData or cfg.types[cfg.default]
self.typeClass = typeData.class
self.typeImage = typeData.image
-- Find if the box has been wrongly substituted.
if cfg.substCheck and args.subst == 'SUBST' then
self.isSubstituted = true
end
-- Find whether we are using a small message box.
if cfg.allowSmall and (
cfg.smallParam and args.small == cfg.smallParam
or not cfg.smallParam and yesno(args.small)
)
then
self.isSmall = true
else
self.isSmall = false
end
-- Add attributes, classes and styles.
if cfg.allowId then
self.id = args.id
self.name = args.name
if self.name then
self:addClass('box-' .. string.gsub(self.name,' ','_'))
end
end
self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks')
for _, class in ipairs(cfg.classes or {}) do
self:addClass(class)
end
if self.isSmall then
self:addClass(cfg.smallClass or 'mbox-small')
end
if yesno(args.hidden) then
self:addClass('infobox editsection')
end
self:addClass(self.typeClass)
self:addClass(args.class)
self.style = args.style
-- Set text style.
self.textstyle = args.textstyle
-- Find if we are on the template page or not. This functionality is only used if useCollapsibleTextFields is set,
-- or if both cfg.templateCategory and cfg.templateCategoryRequireName are set.
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
if self.useCollapsibleTextFields or cfg.templateCategory and cfg.templateCategoryRequireName then
self.name = args.name
if self.name then
local templateName = mw.ustring.match(self.name, '^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$') or self.name
templateName = 'Template:' .. templateName
self.templateTitle = getTitleObject(templateName)
end
self.isTemplatePage = self.templateTitle and mw.title.equals(self.title, self.templateTitle) or false
end
-- Process data for collapsible text fields. At the moment these are only used in {{ambox}}.
if self.useCollapsibleTextFields then
-- Get the self.issue value.
if self.isSmall and args.smalltext then
self.issue = args.smalltext
else
local sect
if args.sect == '' then
sect = '此' .. (cfg.sectionDefault or '頁面')
elseif type(args.sect) == 'string' then
sect = '此' .. args.sect
end
local issue = args.issue
issue = type(issue) == 'string' and issue ~= '' and issue or nil
local text = args.text
text = type(text) == 'string' and text or nil
local issues = {}
tinsert(issues, sect)
tinsert(issues, issue)
tinsert(issues, text)
self.issue = tconcat(issues)
end
-- Get the self.talk value.
local talk = args.talk
if talk == '' -- Show talk links on the template page or template subpages if the talk parameter is blank.
and self.templateTitle
and (mw.title.equals(self.templateTitle, self.title) or self.title:isSubpageOf(self.templateTitle))
then
talk = '#'
elseif talk == '' then
talk = nil
end
if talk then
-- If the talk value is a talk page, make a link to that page. Else assume that it's a section heading,
-- and make a link to the talk page of the current page with that section heading.
local talkTitle = getTitleObject(talk)
local talkArgIsTalkPage = true
if not talkTitle or not talkTitle.isTalkPage then
talkArgIsTalkPage = false
talkTitle = getTitleObject(self.title.text, mw.site.namespaces[self.title.namespace].talk.id)
end
if talkTitle and talkTitle.exists then
local talkText = '相關討論可見於'
if talkArgIsTalkPage then
talkText = format('%s[[%s|%s]].', talkText, talk, talkTitle.prefixedText)
else
talkText = format('%s[[%s#%s|討論頁]].', talkText, talkTitle.prefixedText, talk)
end
self.talk = talkText
end
end
-- Get other values.
local date
if args.date and args.date ~= '' then
date = args.date
elseif args.time == '' and self.isTemplatePage then
date = lang:formatDate('Y年n月j日')
elseif args.time and args.time ~= '' then
date = lang:formatDate('Y年n月j日', args.time)
end
if date then
local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月j日', date) -- 正規化日期
if ok then
date = tempdate
end
end
if date then
self.date = string.format(" <small class='date-container'>''(<span class='date'>%s</span>)''</small>", date)
end
if args.fix and args.fix ~= '' then
self.fix = format("<br /><small>%s</small>", args.fix)
else
self.fix = ''
end
self.info = args.info
end
-- Set the non-collapsible text field. At the moment this is used by all box types other than ambox,
-- and also by ambox when small=yes.
if self.isSmall then
self.text = args.smalltext or args.text
else
self.text = args.text
end
-- Set the below row.
self.below = cfg.below and args.below
-- General image settings.
self.imageCellDiv = not self.isSmall and cfg.imageCellDiv and true or false
self.imageEmptyCell = cfg.imageEmptyCell
if cfg.imageEmptyCellStyle then
self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'
end
-- Left image settings.
local imageLeft = self.isSmall and args.smallimage or args.image
if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none'
or not cfg.imageCheckBlank and imageLeft ~= 'none'
then
self.imageLeft = imageLeft
if not imageLeft then
local imageSize = self.isSmall and (cfg.imageSmallSize or '30x30px') or '40x40px'
self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage or 'Imbox notice.png', imageSize)
end
end
-- Right image settings.
local imageRight = self.isSmall and args.smallimageright or args.imageright
if not (cfg.imageRightNone and imageRight == 'none') then
self.imageRight = imageRight
end
-- Add mainspace categories. At the moment these are only used in {{ambox}}.
if cfg.allowMainspaceCategories then
if args.cat then
args.cat1 = args.cat
end
self.catNums = getArgNums(args, 'cat')
if args.category then
args.category1 = args.category
end
self.categoryNums = getArgNums(args, 'category')
if args.all then
args.all1 = args.all
end
self.allNums = getArgNums(args, 'all')
self.categoryParamNums = union(self.catNums, self.categoryNums)
self.categoryParamNums = union(self.categoryParamNums, self.allNums)
-- The following is roughly equivalent to the old {{Ambox/category}}.
local date
local sortDay
local dayName = {
[1] = '㏠',
[2] = '㏡',
[3] = '㏢',
[4] = '㏣',
[5] = '㏤',
[6] = '㏥',
[7] = '㏦',
[8] = '㏧',
[9] = '㏨',
[10] = '㏩',
[11] = '㏪',
[12] = '㏫',
[13] = '㏬',
[14] = '㏭',
[15] = '㏮',
[16] = '㏯',
[17] = '㏰',
[18] = '㏱',
[19] = '㏲',
[20] = '㏳',
[21] = '㏴',
[22] = '㏵',
[23] = '㏶',
[24] = '㏷',
[25] = '㏸',
[26] = '㏹',
[27] = '㏺',
[28] = '㏻',
[29] = '㏼',
[30] = '㏽',
[31] = '㏾'
}
if args.date and args.date ~= '' then
date = args.date
local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月', date) -- 正規化日期
if ok then
date = tempdate
end
elseif args.time and args.time ~= '' then
date = lang:formatDate('Y年n月', args.time)
sortDay = lang:formatDate('j', args.time)
sortDay = tonumber(sortDay)
sortDay = dayName[sortDay]
end
date = type(date) == 'string' and date
local preposition = '自'
for _, num in ipairs(self.categoryParamNums) do
local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)]
local allCat = args['all' .. tostring(num)]
mainCat = type(mainCat) == 'string' and mainCat
allCat = type(allCat) == 'string' and allCat
if mainCat and date and date ~= '' then
local catTitle = format('%s%s%s', preposition, date, mainCat)
if sortDay then
self:addCat('main', catTitle, sortDay)
else
self:addCat('main', catTitle)
end
catTitle = getTitleObject('Category:' .. catTitle)
if not catTitle or not catTitle.exists then
self:addCat('main', '模板中使用无效日期参数的条目')
end
elseif mainCat and (not date or date == '') then
self:addCat('main', mainCat)
end
if allCat then
self:addCat('main', allCat)
end
end
end
-- Add template-namespace categories.
if cfg.templateCategory then
if cfg.templateCategoryRequireName then
if self.isTemplatePage then
self:addCat('template', cfg.templateCategory)
end
elseif not self.title.isSubpage then
self:addCat('template', cfg.templateCategory)
end
end
-- Add template error category.
if cfg.templateErrorCategory then
local templateErrorCategory = cfg.templateErrorCategory
local templateCat, templateSort
if not self.name and not self.title.isSubpage then
templateCat = templateErrorCategory
elseif self.isTemplatePage then
local paramsToCheck = cfg.templateErrorParamsToCheck or {}
local count = 0
for i, param in ipairs(paramsToCheck) do
if not args[param] then
count = count + 1
end
end
if count > 0 then
templateCat = templateErrorCategory
templateSort = tostring(count)
end
if self.categoryNums and #self.categoryNums > 0 then
templateCat = templateErrorCategory
templateSort = 'C'
end
end
self:addCat('template', templateCat, templateSort)
end
-- Categories for all namespaces.
if self.invalidTypeError then
local allSort = (self.nsid == 0 and 'Main:' or '') .. self.title.prefixedText
self:addCat('all', '需要修复的信息框', allSort)
end
if self.isSubstituted then
self:addCat('all', '錯誤使用替換引用的頁面')
end
-- Convert category tables to strings and pass them through [[Module:Category handler]].
self.categories = categoryHandler{
main = tconcat(self.mainCats or {}),
template = tconcat(self.templateCats or {}),
all = tconcat(self.allCats or {}),
nocat = args.nocat,
demospace = self.demospace,
page = self.pageTitle and self.pageTitle.prefixedText or nil
}
end
function box:export()
local root = mw.html.create()
-- Add the subst check error.
if self.isSubstituted and self.name then
root
:tag('b')
:addClass('error')
:wikitext(format(
'模板<code>%s[[Template:%s|%s]]%s</code>被錯誤地替代。',
mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')
))
end
-- Create the box table.
local boxTable = root:tag('table')
boxTable
:attr('id', self.id)
for i, class in ipairs(self.classes or {}) do
boxTable
:addClass(class)
end
boxTable
:cssText(self.style)
:attr('role', 'presentation')
-- Add the left-hand image.
local row = boxTable:tag('tr')
if self.imageLeft then
local imageLeftCell = row:tag('td'):addClass('mbox-image')
if self.imageCellDiv then
-- If we are using a div, redefine imageLeftCell so that the image is inside it.
-- Divs use style="width: 52px;", which limits the image width to 52px. If any
-- images in a div are wider than that, they may overlap with the text or cause
-- other display problems.
imageLeftCell = imageLeftCell:tag('div'):css('width', '52px')
end
imageLeftCell
:wikitext(self.imageLeft)
elseif self.imageEmptyCell then
-- Some message boxes define an empty cell if no image is specified, and some don't.
-- The old template code in templates where empty cells are specified gives the following hint:
-- "No image. Cell with some width or padding necessary for text cell to have 100% width."
row:tag('td')
:addClass('mbox-empty-cell')
:cssText(self.imageEmptyCellStyle)
end
-- Add the text.
local textCell = row:tag('td'):addClass('mbox-text')
if self.useCollapsibleTextFields then
-- The message box uses advanced text parameters that allow things to be collapsible. At the
-- moment, only ambox uses this.
textCell
:cssText(self.textstyle)
local textCellSpan = textCell:tag('div')
textCellSpan
:addClass('mbox-text-span')
:wikitext(self.issue)
if not self.isSmall then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.talk and self.talk)
end
textCellSpan
:wikitext(self.date and self.date)
if not self.isSmall and self.fix ~= '' then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.fix and self.fix)
end
if not self.isSmall then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.info and self.info)
end
else
-- Default text formatting - anything goes.
textCell
:cssText(self.textstyle)
:wikitext(self.text)
end
-- Add the right-hand image.
if self.imageRight then
local imageRightCell = row:tag('td'):addClass('mbox-imageright')
if self.imageCellDiv then
imageRightCell = imageRightCell:tag('div'):css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.
end
imageRightCell
:wikitext(self.imageRight)
end
-- Add the below row.
if self.below then
boxTable:tag('tr')
:tag('td')
:attr('colspan', self.imageRight and '3' or '2')
:addClass('mbox-text')
:cssText(self.textstyle)
:wikitext(self.below)
end
-- Add error message for invalid type parameters.
if self.invalidTypeError then
root
:tag('div')
:css('text-align', 'center')
:wikitext(format('此訊息框使用無效的「type=%s」參數,需要修復。', self.type or ''))
end
-- Add categories.
root
:wikitext(self.categories)
return tostring(root)
end
local function main(boxType, args)
local outputBox = box.new()
outputBox:setTitle(args)
local cfg = outputBox:getConfig(boxType)
args = outputBox:removeBlankArgs(cfg, args)
outputBox:setBoxParameters(cfg, args)
return outputBox:export()
end
local function makeWrapper(boxType)
return function (frame)
local args = getArgs(frame, {trim = false, removeBlanks = false})
return main(boxType, args)
end
end
local p = {
main = main,
mbox = makeWrapper('mbox')
}
for boxType in pairs(cfgTables) do
p[boxType] = makeWrapper(boxType)
end
return p
272fc832b204569beebe8b740e600f3f69aafc11
Module:Navbox
828
75
144
2024-07-21T06:41:10Z
zhwp>Shizhao
0
ep
Scribunto
text/plain
--
-- This module will implement {{Navbox}}
--
local p = {}
local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized
local args
local tableRowAdded = false
local border
local listnums = {}
local function trim(s)
return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end
local function addNewline(s)
if s:match('^[*:;#]') or s:match('^{|') then
return '\n' .. s ..'\n'
else
return s
end
end
local function addTableRow(tbl)
-- If any other rows have already been added, then we add a 2px gutter row.
if tableRowAdded then
tbl
:tag('tr')
:css('height', '2px')
:tag('td')
:attr('colspan', 3)
end
tableRowAdded = true
return tbl:tag('tr')
end
local function renderNavBar(titleCell)
-- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
-- or right to keep the title centered.
local spacerSide = nil
if args.navbar == 'off' then
-- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
-- also no show/hide link, then we need a spacer on the right to achieve the left shift.
if args.state == 'plain' then spacerSide = 'right' end
elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox' and (border == 'subgroup' or border == 'child' or border == 'none')) then
-- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
if args.state ~= 'plain' then spacerSide = 'left' end
else
-- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
-- to balance out the width of the navbar.
if args.state == 'plain' then spacerSide = 'right' end
titleCell:wikitext(navbar{
args.name,
mini = 1,
fontstyle = 'color:inherit;' .. (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;'
})
end
-- Render the spacer div.
if spacerSide then
titleCell
:tag('span')
:css('float', spacerSide)
:css('position', 'absolute')
:css(spacerSide, '1em')
:css('margin-' .. (spacerSide == 'left' and 'right' or 'left'), '0.5em')
:css('padding-' .. spacerSide, '0.2em')
:wikitext(' ')
end
end
--
-- Title row
--
local function renderTitleRow(tbl)
if not args.title then return end
local titleRow = addTableRow(tbl)
if args.titlegroup then
titleRow
:tag('th')
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.titlegroupclass)
:cssText(args.basestyle)
:cssText(args.groupstyle)
:cssText(args.titlegroupstyle)
:wikitext(args.titlegroup)
end
local titleCell = titleRow:tag('th'):attr('scope', 'col')
if args.titlegroup then
titleCell
:css('border-left', '2px solid #fdfdfd')
:css('width', '100%')
end
local titleColspan = 2
if args.imageleft then titleColspan = titleColspan + 1 end
if args.image then titleColspan = titleColspan + 1 end
if args.titlegroup then titleColspan = titleColspan - 1 end
titleCell
:cssText(args.basestyle)
:cssText(args.titlestyle)
:addClass('navbox-title')
:addClass(args.titleclass)
:attr('colspan', titleColspan)
renderNavBar(titleCell)
titleCell
:tag('div')
:css('font-size', '110%')
:wikitext(addNewline(args.title))
end
--
-- Above/Below rows
--
local function getAboveBelowColspan()
local ret = 2
if args.imageleft then ret = ret + 1 end
if args.image then ret = ret + 1 end
return ret
end
local function renderAboveRow(tbl)
if not args.above then return end
addTableRow(tbl)
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.aboveclass)
:cssText(args.basestyle)
:cssText(args.abovestyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(addNewline(args.above))
end
local function renderBelowRow(tbl)
if not args.below then return end
addTableRow(tbl)
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.belowclass)
:cssText(args.basestyle)
:cssText(args.belowstyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(addNewline(args.below))
end
--
-- List rows
--
local function renderListRow(tbl, listnum)
local row = addTableRow(tbl)
if listnum == 1 and args.imageleft then
row
:tag('td')
:addClass('navbox-image')
:addClass(args.imageclass)
:css('width', '0%')
:css('padding', '0px 2px 0px 0px')
:cssText(args.imageleftstyle)
:attr('rowspan', 2 * #listnums - 1)
:tag('div')
:wikitext(addNewline(args.imageleft))
end
if args['group' .. listnum] then
local groupCell = row:tag('th')
groupCell
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.groupclass)
:cssText(args.basestyle)
if args.groupwidth then
groupCell:css('width', args.groupwidth)
end
groupCell
:cssText(args.groupstyle)
:cssText(args['group' .. listnum .. 'style'])
:wikitext(args['group' .. listnum])
end
local listCell = row:tag('td')
if args['group' .. listnum] then
listCell
:css('text-align', 'left')
:css('border-left-width', '2px')
:css('border-left-style', 'solid')
else
listCell:attr('colspan', 2)
end
if not args.groupwidth then
listCell:css('width', '100%')
end
local isOdd = (listnum % 2) == 1
local rowstyle = args.evenstyle
if isOdd then rowstyle = args.oddstyle end
local evenOdd
if args.evenodd == 'swap' then
if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
else
if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
end
listCell
:css('padding', '0px')
:cssText(args.liststyle)
:cssText(rowstyle)
:cssText(args['list' .. listnum .. 'style'])
:addClass('navbox-list')
:addClass('navbox-' .. evenOdd)
:addClass(args.listclass)
:tag('div')
:css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:wikitext(addNewline(args['list' .. listnum]))
if listnum == 1 and args.image then
row
:tag('td')
:addClass('navbox-image')
:addClass(args.imageclass)
:css('width', '0%')
:css('padding', '0px 0px 0px 2px')
:cssText(args.imagestyle)
:attr('rowspan', 2 * #listnums - 1)
:tag('div')
:wikitext(addNewline(args.image))
end
end
--
-- Tracking categories
--
local function needsHorizontalLists()
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent', 'hlist hlist-pipe', 'hlist hlist-hyphen'}
for i, cls in ipairs(listClasses) do
if args.listclass == cls or args.bodyclass == cls then
return false
end
end
return true
end
local function hasBackgroundColors()
return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
end
local function argNameAndRealTitleAreDifferent()
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
if args.name ~= mw.title.getCurrentTitle().text then
return true
end
return false
end
local function getTrackingCategories()
local cats = {}
if needsHorizontalLists() then table.insert(cats, '没有使用水平列表的导航框') end
if hasBackgroundColors() then table.insert(cats, '使用背景颜色的导航框') end
if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name參數和實際不同的導航框') end
return cats
end
local function renderTrackingCategories(builder)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 10 then return end -- not in template space
local subpage = title.subpageText
if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
for i, cat in ipairs(getTrackingCategories()) do
builder:wikitext('[[Category:' .. cat .. ']]')
end
end
--
-- Main navbox tables
--
local function renderMainTable()
local tbl = mw.html.create('table')
:attr('cellspacing', 0)
:addClass('nowraplinks')
:addClass(args.bodyclass)
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
if args.state == 'collapsed' then args.state = 'mw-collapsed' end
tbl
:addClass('mw-collapsible')
:addClass(args.state or 'autocollapse')
end
tbl:css('border-spacing', 0)
if border == 'subgroup' or border == 'child' or border == 'none' then
tbl
:addClass('navbox-subgroup')
:cssText(args.bodystyle)
:cssText(args.style)
else -- regular navobx - bodystyle and style will be applied to the wrapper table
tbl
:addClass('navbox-inner')
:css('background', 'transparent')
:css('color', 'inherit')
end
tbl:cssText(args.innerstyle)
renderTitleRow(tbl)
renderAboveRow(tbl)
for i, listnum in ipairs(listnums) do
renderListRow(tbl, listnum)
end
renderBelowRow(tbl)
return tbl
end
function p._navbox(navboxArgs)
args = navboxArgs
for k, v in pairs(args) do
local listnum = ('' .. k):match('^list(%d+)$')
if listnum then table.insert(listnums, tonumber(listnum)) end
end
table.sort(listnums)
border = trim(args.border or args[1] or '')
-- render the main body of the navbox
local tbl = renderMainTable()
-- render the appropriate wrapper around the navbox, depending on the border param
local res = mw.html.create()
if border == 'none' then
res:node(tbl)
elseif border == 'subgroup' or border == 'child' then
-- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
-- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
-- padding being applied, and at the end add a <div> to balance out the parent's </div>
res
:wikitext('</div>') -- mw.html 未支持 unclosed
:node(tbl)
:wikitext('<div>') -- mw.html 未支持 unclosed
else
res
:tag('table')
:attr('cellspacing', 0)
:addClass('navbox')
:css('border-spacing', 0)
:cssText(args.bodystyle)
:cssText(args.style)
:tag('tr')
:tag('td')
:css('padding', '2px')
:node(tbl)
end
renderTrackingCategories(res)
return tostring(res)
end
function p.navbox(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame, {wrappers = 'Template:Navbox'})
-- Read the arguments in the order they'll be output in, to make references number in the right order.
local _
_ = args.title
_ = args.above
for i = 1, 35 do
_ = args["group" .. tostring(i)]
_ = args["list" .. tostring(i)]
end
_ = args.below
return p._navbox(args)
end
return p
6864182981324b61a13042fc742049007401dfa4
Template:Block/styles.css
10
318
661
2024-07-21T19:28:58Z
zhwp>What7what8
0
sanitized-css
text/css
.inline-text-blocked {
color: transparent !important;
background-color: #000000;
transition: color 0.25s;
}
.inline-text-blocked *, .inline-text-blocked a {
color: transparent !important;
background-color: transparent !important;
cursor: default !important;
text-decoration: none !important;
transition: color 0.25s !important;
}
.inline-text-blocked::selection, .inline-text-blocked *::selection {
color: #ffffff !important;
background: #404040;
background: rgba(0, 0, 0, 0.75);
}
@media (pointer: coarse) {
.inline-text-blocked:hover, .inline-text-blocked *:hover, .inline-text-blocked a:hover, .inline-text-blocked a:active, .inline-text-blocked a *:hover, .inline-text-blocked a *:active {
color: #ffffff !important;
}
}
@media (pointer: fine), (pointer: none) {
.inline-text-blocked:focus {
color: #ffffff !important;
}
}
/* hd = hard, dark */
.inline-text-block-hd {
color: transparent !important;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd a,
.inline-text-block-hd .new,
.inline-text-block-hd * {
color: transparent !important;
background: transparent !important
}
.inline-text-block-hd::selection,
.inline-text-block-hd *::selection {
color: #ffffff;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd a::selection {
color: #88bbff;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd .new::selection {
color: #ffbb88;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
@media (pointer: coarse), (pointer: none) {
.inline-text-block-hd:hover,
.inline-text-block-hd:active,
.inline-text-block-hd:hover *,
.inline-text-block-hd:active * {
color: #ffffff !important;
transition: 0.15s linear
}
.inline-text-block-hd:hover a,
.inline-text-block-hd:active a {
color: #88bbff !important;
transition: 0.15s linear
}
.inline-text-block-hd:hover .new,
.inline-text-block-hd:active .new {
color: #ffbb88 !important;
transition: 0.15s linear
}
}
/* sl = soft, light */
.inline-text-block-sl,
.inline-text-block-sl a,
.inline-text-block-sl .new {
color: transparent !important
}
.inline-text-block-sl::selection {
color: #000000
}
.inline-text-block-sl a::selection {
color: #0033cc
}
.inline-text-block-sl .new::selection {
color: #cc3300
}
@media (pointer: coarse), (pointer: none) {
.inline-text-block-sl:hover,
.inline-text-block-sl:active {
color: #000000 !important;
transition: 0.15s linear
}
.inline-text-block-sl:hover a,
.inline-text-block-sl:active a {
color: #0033cc !important;
transition: 0.15s linear
}
.inline-text-block-sl:hover .new,
.inline-text-block-sl:active .new {
color: #cc3300 !important;
transition: 0.15s linear
}
}
/* hsd = hover-display, soft, dark */
.inline-text-block-hsd {
color: transparent !important;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hsd a,
.inline-text-block-hsd .new {
color: transparent
}
.inline-text-block-hsd:hover,
.inline-text-block-hsd:active,
.inline-text-block-hsd::selection {
color: #ffffff !important;
transition: 0.15s linear
}
.inline-text-block-hsd:hover a,
.inline-text-block-hsd:active a,
.inline-text-block-hsd a::selection {
color: #88bbff;
transition: 0.15s linear
}
.inline-text-block-hsd:hover .new,
.inline-text-block-hsd:active .new,
.inline-text-block-hsd .new::selection {
color: #ffbb88;
transition: 0.15s linear
}
/* hsl = hover-display, soft, light */
.inline-text-block-hsl,
.inline-text-block-hsl a,
.inline-text-block-hsl .new {
color: transparent !important
}
.inline-text-block-hsl:hover,
.inline-text-block-hsl:active,
.inline-text-block-hsl::selection {
color: #000000 !important;
transition: 0.15s linear
}
.inline-text-block-hsl:hover a,
.inline-text-block-hsl:active a,
.inline-text-block-hsl a::selection {
color: #0033cc !important;
transition: 0.15s linear
}
.inline-text-block-hsl:hover .new,
.inline-text-block-hsl:active .new,
.inline-text-block-hsl .new::selection {
color: #cc3300 !important;
transition: 0.15s linear
}
583d9f3d313fba42040a2ced0572987f43964ead
Template:Cmbox/style.css
10
257
531
2024-07-21T20:13:52Z
zhwp>Jimmy Xu
0
[[Cat:保護狀態與保護標誌不符的頁面]]
sanitized-css
text/css
.cmbox {
margin: 3px 0;
border-collapse: collapse;
border: 1px solid #a2a9b1;
background-color: #dfe8ff; /* Default "notice" blue */
box-sizing: border-box;
}
.cmbox-speedy {
border: 4px solid #b32424; /* Red */
background-color: #ffdbdb; /* Pink */
}
.cmbox-delete {
background-color: #ffdbdb; /* Pink */
}
.cmbox-content {
background-color: #ffe7ce; /* Orange */
}
.cmbox-style {
background-color: #fff9db; /* Yellow */
}
.cmbox-move {
background-color: #e4d8ff; /* Purple */
}
.cmbox-protection {
background-color: #efefe1; /* Gray-gold */
}
.cmbox .mbox-text {
border: none;
/* @noflip */
padding: 0.25em 0.9em;
width: 100%;
}
.cmbox .mbox-image {
border: none;
/* @noflip */
padding: 2px 0 2px 0.9em;
text-align: center;
}
.cmbox .mbox-imageright {
border: none;
/* @noflip */
padding: 2px 0.9em 2px 0;
text-align: center;
}
/* An empty narrow cell */
.cmbox .mbox-empty-cell {
border: none;
padding: 0;
width: 1px;
}
.cmbox .mbox-invalid-type {
text-align: center;
}
@media (min-width: 720px) {
.cmbox {
margin: 3px 10%;
}
}
/* flipped lightness in hsl space except the main cmbox is the main page blue */
html.skin-theme-clientpref-night .cmbox {
background-color: #0d1a27; /* Default "notice" blue */
}
html.skin-theme-clientpref-night .cmbox-speedy,
html.skin-theme-clientpref-night .cmbox-delete {
background-color: #300; /* Pink */
}
html.skin-theme-clientpref-night .cmbox-content {
background-color: #331a00; /* Orange */
}
html.skin-theme-clientpref-night .cmbox-style {
background-color: #332b00; /* Yellow */
}
html.skin-theme-clientpref-night .cmbox-move {
background-color: #08001a; /* Purple */
}
html.skin-theme-clientpref-night .cmbox-protection {
background-color: #212112; /* Gray-gold */
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cmbox {
background-color: #0d1a27; /* Default "notice" blue */
}
html.skin-theme-clientpref-os .cmbox-speedy,
html.skin-theme-clientpref-os .cmbox-delete {
background-color: #300; /* Pink */
}
html.skin-theme-clientpref-os .cmbox-content {
background-color: #331a00; /* Orange */
}
html.skin-theme-clientpref-os .cmbox-style {
background-color: #332b00; /* Yellow */
}
html.skin-theme-clientpref-os .cmbox-move {
background-color: #08001a; /* Purple */
}
html.skin-theme-clientpref-os .cmbox-protection {
background-color: #212112; /* Gray-gold */
}
}
714e8d532c88a9aad9fc9fdcf152d0044514034c
Module:CGroup/IT
828
133
266
2024-07-23T05:58:58Z
zhwp>Tommylung
0
[[WP:UNDO|撤销]][[Special:Contributions/自由雨日|自由雨日]]([[User talk:自由雨日|讨论]])的版本83518265:單向轉換規則是無法以zh-tw來覆蓋zh-hk和zh-mo
Scribunto
text/plain
-- 用法: Item('原文', '轉換規則')
local Item = require('Module:CGroup/core').Item;
return {
name = 'IT',
description = '-{zh-cn:信息技术; zh-sg:资讯科技; zh-my:资讯科技; zh-tw:資訊科技;}-',
content = {
{ type = 'text', text = [=[
== A ==
]=] },
Item('AI', 'zh-cn:人工智能; zh-sg:人工智慧; zh-tw:人工智慧; zh-hk:人工智能;'),
-- 容易過度轉換,僅單向轉換
Item('access', '存取=>zh-cn:访问; 存取=>zh-tw:存取;'),
Item('access', '存取權=>zh-cn:访问权; 存取權=>zh-tw:存取權;'),
Item('access', '访问权=>zh-cn:访问权; 访问权=>zh-tw:存取權;'),
Item('access', '存取權限=>zh-cn:访问权限; 存取權限=>zh-tw:存取權限;'),
Item('access', '访问权限=>zh-cn:访问权限; 访问权限=>zh-tw:存取權限;'),
Item('access control list', 'zh-cn:访问控制表; zh-tw:存取控制列表;'),
Item('access control list', '存取控制串列=>zh-cn:访问控制表; 存取控制串列=>zh-sg:访问控制表; 存取控制串列=>zh-my:访问控制表; zh-tw:存取控制列表;'),
Item('access Multiplexer', 'zh-cn:接入复用器; zh-tw:接取多工器;'),
Item('access Point', 'zh-cn:接入点; zh-tw:存取點;'),
Item('account', 'zh-cn:账号; zh-tw:帳號; zh-hk:帳號;'),
Item('account', 'zh-cn:账户; zh-tw:帳戶; zh-hk:帳戶;'),
Item('activation', 'zh-cn:激活; zh-tw:啟用;'),
Item('activation function', 'zh-cn:激活函数; zh-tw:啟用功能;'),
Item('adapter', 'zh-cn:适配器; zh-tw:配接器;'),
Item('add-on', 'zh-cn:附加组件; zh-tw:附加元件;'),
Item('address', 'zh-cn:地址; zh-tw:位址; zh-hk:地址;'),
Item('address bar', 'zh-cn:地址栏; zh-tw:網址列; zh-hk:地址列;'),
Item('addressing', 'zh-cn:寻址; zh-tw:定址; zh-hk:定址;'),
Item('addressing modes', 'zh-cn:寻址模式; zh-tw:定址模式; zh-hk:定址模式;'),
Item('advanced', 'zh-cn:高级; zh-tw:進階;'),
Item('advertising area', 'zh-cn:广告位; zh-tw:廣告區;'),
Item('agent-oriented programming', 'zh-cn:面向代理编程; zh-tw:代理人導向程式設計;'),
Item('album (online)', 'zh-cn:相册; zh-my:相簿; zh-tw:相簿;'),
Item('algorithm', 'zh-cn:算法; zh-tw:演算法;'),
Item('allocation unit', 'zh-cn:分配单元; zh-tw:單位配置;'),
Item('analog', 'zh-cn:模拟; zh-tw:類比; zh-hk:模擬;'),
Item('analog broadcasting', 'zh-cn:模拟广播; zh-tw:類比廣播; zh-hk:模擬廣播;'),
Item('analog television', 'zh-cn:模拟电视; zh-tw:類比電視; zh-hk:模擬電視;'),
-- 港台的「殺毒」有時有「清除病毒」的意思
Item('antivirus', 'zh-cn:杀毒; zh-tw:防毒;'),
Item('AOL', 'zh:美國在線; zh-cn:美国在线; zh-tw:美國線上;'),
Item('application', 'zh:應用程序; zh-cn:应用程序; zh-my:应用程式; zh-hant:應用程式;'),
Item('application programming interface', 'zh:應用程序接口; zh-cn:应用程序接口; zh:应用程式介面; zh-tw:應用程式介面;'),
Item('archive', 'zh:壓縮包; zh-cn:压缩包; zh-my:压缩档; zh-tw:壓縮檔;'),
Item('array (RAID)', 'zh-cn:服务器阵列; zh-sg:伺服器阵列; zh-tw:伺服器陣列;'),
Item('array (RAID)', 'zh-cn:硬盘阵列; zh-tw:硬碟陣列;'),
Item('array (RAID)', 'zh-cn:磁盘阵列; zh-tw:磁碟陣列;'),
Item('array (RAID)', 'zh-cn:阵列服务器; zh-sg:阵列伺服器; zh-tw:陣列伺服器;'),
Item('array (RAID)', 'zh-cn:阵列硬盘; zh-tw:陣列硬碟;'),
Item('array', 'zh-cn:数组; zh-tw:陣列;'),
Item('Artificial Neural', 'zh:人工神經; zh-cn:人工神经; zh-tw:類神經;'),
Item('assembler', 'zh-cn:汇编; zh-tw:組譯;'),
Item('Assembly language', 'zh-cn:汇编语言; zh-tw:組合語言; zh-hk:匯編語言;'),
Item('assembly mnemonic', 'zh-cn:助记符; zh-tw:輔助記憶碼;'),
Item('assignment operator', 'zh-cn:赋值运算符; zh-tw:設定運算子;'),
Item('assignment operator', '賦值運算符=>zh-tw:設定運算子; 賦值運算符=>zh-hk:設定運算子; 賦值運算符=>zh-mo:設定運算子;'),
Item('assignment operator', '赋值操作符=>zh-tw:設定運算子; 赋值操作符=>zh-hk:設定運算子; 赋值操作符=>zh-mo:設定運算子;'),
Item('assignment operator', '賦值操作符=>zh-tw:設定運算子; 賦值操作符=>zh-hk:設定運算子; 賦值操作符=>zh-mo:設定運算子;'),
Item('asynchrony', 'zh-cn:异步; zh-tw:非同步;'),
Item('asynchrony', '異步=>zh-tw:非同步; 異步=>zh-hk:非同步; 異步=>zh-mo:非同步;'),
Item('average bitrate', 'zh-cn:平均码率; zh-tw:平均位元速率;'),
Item('audio', 'zh-cn:音频; zh-tw:音訊; zh-hk:音頻;'),
Item('audio track', 'zh-cn:音频轨; zh-tw:音訊軌; zh-hk:音頻軌;'),
Item('audio input', 'zh-cn:音频输入; zh-tw:音訊輸入; zh-hk:音頻輸入;'),
Item('audio output', 'zh-cn:音频输出; zh-tw:音訊輸出; zh-hk:音頻輸出;'),
Item('audio file', 'zh-cn:音频文件; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio file', 'zh-cn:音频文档; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio file', 'zh-cn:音频档; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio profiles', 'zh-cn:情景模式; zh-tw:音訊設定檔;'),
Item('audit', 'zh-cn:审核; zh-tw:稽核;'),
Item('augmented reality', 'zh:增強現實; zh-cn:增强现实; zh-sg:扩增实境; zh-tw:擴增實境; zh-hk:擴張實境;'),
{ type = 'text', text = [[
== B ==
]] },
Item('back chaining', 'zh-cn:反链接; zh-tw:反鏈結;'),
Item('background traffic', 'zh-cn:后台流量; zh-tw:背景流量;'),
Item('backward compatible', '向后兼容=>zh-tw:向下相容; 向后兼容=>zh-hk:向下相容; 向后兼容=>zh-mo:向下相容;'),
Item('backward compatible', '向後兼容=>zh-tw:向下相容; 向後兼容=>zh-hk:向下相容; 向後兼容=>zh-mo:向下相容;'),
Item('bad sector', 'zh-cn:坏道; zh-tw:壞軌;'),
Item('band width', 'zh-cn:带宽; zh-tw:頻寬;'),
Item('base class', 'zh-cn:基类; zh-tw:基礎類別;'),
Item('base name', 'zh-cn:文件主名; zh-tw:主檔名;'),
Item('base type', 'zh-cn:基类型; zh-tw:基本類型;'),
Item('baseband', 'zh-cn:基带; zh-hk:基帶; zh-tw:基頻;'),
Item('batch', 'zh-cn:批量; zh-tw:批次;'),
Item('batch', 'zh-cn:批处理; zh-tw:批次處理;'),
Item('batch file', 'zh-cn:批处理文件; zh-tw:批次檔;'),
Item('batch programs', 'zh-cn:批处理程序; zh-tw:批次程式;'),
Item('Berkeley Software Distribution', 'zh-cn:伯克利软件套件; zh-tw:柏克萊軟體套件; zh-hk:柏克萊軟件套件;'),
Item('big data', 'zh-cn:大数据; zh-tw:大數據;'),
Item('Bill Gates', 'zh-cn:盖茨; zh-tw:蓋茲; zh-hk:蓋茨;'),
Item('binary', '二叉=>zh-tw:二元; 二叉=>zh-hk:二元; 二叉=>zh-mo:二元;'),
Item('binary function', 'zh-cn:双参函数; zh-tw:二元函數;'),
Item('binary heap', 'zh-cn:二叉堆; zh-tw:二元堆積; zh-hk:二叉堆積;'),
Item('binary linked list', 'zh-cn:二叉链表; zh-tw:二元連結串列;'),
Item('binary linked list', '二叉鏈表=>zh-tw:二元連結串列; 二叉鏈表=>zh-hk:二元連結串列; 二叉鏈表=>zh-mo:二元連結串列;'),
Item('binary search tree', 'zh-cn:二叉搜索树; zh-tw:二元搜尋樹; zh-hk:二叉搜尋樹;'),
Item('binary search tree', '二叉查找树=>zh-tw:二元搜尋樹; 二叉查找树=>zh-hk:二叉搜尋樹; 二叉查找树=>zh-mo:二叉搜尋樹;'),
Item('binary tree', 'zh-cn:二叉树; zh-tw:二元樹; zh-hk:二叉樹;'),
Item('binding', 'zh-cn:绑定; zh-tw:繫結;'),
Item('bit', 'zh-cn:比特; zh-sg:位元; zh-tw:位元;'),
Item('bit', '二进制位=>zh-sg:位元; 二进制位=>zh-my:位元; 二进制位=>zh-tw:位元; 二进制位=>zh-hk:位元; 二进制位=>zh-mo:位元;'),
Item('bit (4-bit)', 'zh-cn:4位; zh-tw:4位元;'),
Item('bit (8-bit)', 'zh-cn:8位; zh-tw:8位元;'),
-- 有可能過度轉換,編輯時須注意
Item('bit (12-bit)', 'zh-cn:12位; zh-tw:12位元;'),
Item('bit (16-bit)', 'zh-cn:16位; zh-tw:16位元;'),
Item('bit (18-bit)', 'zh-cn:18位; zh-tw:18位元;'),
Item('bit (24-bit)', 'zh-cn:24位; zh-tw:24位元;'),
Item('bit (31-bit)', 'zh-cn:31位; zh-tw:31位元;'),
Item('bit (32-bit)', 'zh-cn:32位; zh-tw:32位元;'),
Item('bit (36-bit)', 'zh-cn:36位; zh-tw:36位元;'),
Item('bit (48-bit)', 'zh-cn:48位; zh-tw:48位元;'),
Item('bit (60-bit)', 'zh-cn:60位; zh-tw:60位元;'),
Item('bit (64-bit)', 'zh-cn:64位; zh-tw:64位元;'),
Item('bit (80-bit)', 'zh-cn:80位; zh-tw:80位元;'),
Item('bit (128-bit)', 'zh-cn:128位; zh-tw:128位元;'),
Item('bit error rate', 'zh-cn:比特误码率; zh-tw:位元錯誤率;'),
Item('bit error rate', '误比特率=>zh-tw:位元錯誤率; 误比特率=>zh-hk:位元錯誤率; 误比特率=>zh-mo:位元錯誤率;'),
Item('bit field', 'zh-cn:位段; zh-tw:位元欄;'),
Item('bit pattern', 'zh-cn:位模式; zh-tw:位元型樣;'),
Item('bit pattern', '位元模式=>zh-cn:位模式; 位元模式=>zh-sg:位模式; 位元模式=>zh-my:位模式;'),
Item('bit string', 'zh-cn:位串; zh-tw:位元串;'),
Item('Bitmap', '栅格图=>zh-tw:點陣圖;'),
Item('Bitmap', 'zh-cn:位图; zh-tw:點陣圖;'),
Item('bitrate', 'zh-cn:比特率; zh-tw:位元速率;'),
Item('bitrate', '码率=>zh-tw:位元速率; 码率=>zh-hk:位元速率; 码率=>zh-mo:位元速率;'),
Item('bitrate', '碼率=>zh-tw:位元速率; 碼率=>zh-hk:位元速率; 碼率=>zh-mo:位元速率;'),
Item('bitrate', '荷码率=>zh-tw:位元速率; 荷码率=>zh-hk:位元速率; 荷码率=>zh-mo:位元速率;'),
Item('bitrate', '荷碼率=>zh-tw:位元速率; 荷碼率=>zh-hk:位元速率; 荷碼率=>zh-mo:位元速率;'),
Item('bitwise', 'zh-cn:按位; zh-tw:按位元;'),
Item('bitwise operation', 'zh-cn:位操作; zh-tw:位元運算;'),
Item('bitwise operation', '位元运算=>zh-cn:位操作; 位元运算=>zh-sg:位操作; 位元运算=>zh-my:位操作;'),
Item('bitwise operation', '位元操作=>zh-cn:位操作; 位元操作=>zh-sg:位操作; 位元操作=>zh-my:位操作;'),
Item('bitwise operation', '位运算=>zh-tw:位元運算; 位运算=>zh-hk:位元運算; 位运算=>zh-mo:位元運算;'),
Item('bitwise operation', '位運算=>zh-tw:位元運算; 位運算=>zh-hk:位元運算; 位運算=>zh-mo:位元運算;'),
Item('black box testing', 'zh-cn:黑盒测试; zh-tw:黑箱測試;'),
Item('Blade Server', 'zh-cn:刀片服务器; zh-tw:刀鋒伺服器;'),
Item('blank screen', 'zh-cn:黑屏; zh-tw:黑畫面;'),
Item('block', 'zh-cn:屏蔽; zh-tw:封鎖;'),
Item('block (Unicode)', '区段=>zh-cn:区块; 区段=>zh-sg:区块; 区段=>zh-my:区块;'),
Item('block chaining', 'zh-cn:组链接; zh-tw:塊鏈結;'),
Item('block chaining', 'zh-cn:区块链接; zh-tw:區塊鏈結;'),
Item('block cipher', 'zh-cn:分组密码; zh-tw:區塊加密法;'),
Item('block diagram', 'zh-cn:框图; zh-tw:方塊圖;'),
Item('blog', 'zh-cn:博客; zh-tw:部落格; zh-hk:網誌; zh-my:部落格;'),
Item('bluetooth', '藍芽=>zh-hans:蓝牙; 藍芽=>zh-hant:藍牙; 藍芽=>zh-cn:蓝牙; 藍芽=>zh-tw:藍牙; 藍芽=>zh-hk:藍牙;'),
Item('bluetooth', '蓝芽=>zh-hans:蓝牙; 蓝芽=>zh-hant:藍牙; 蓝芽=>zh-cn:蓝牙; 蓝芽=>zh-tw:藍牙; 蓝芽=>zh-hk:藍牙;'),
Item('Blue Screen', 'zh-hant:藍屏; zh-cn:蓝屏; zh-tw:藍白畫面; zh-hk:藍畫面;'),
Item('Blue Screen of Death', 'zh-hant:藍屏死機; zh-cn:蓝屏死机; zh-tw:藍白當機; zh-hk:藍畫面死機;'),
Item('boot disk', 'zh-cn:启动盘; zh-tw:啟動磁碟;'),
Item('boot loader', 'zh-cn:启动引导程序; zh-tw:啟動載入程式;'),
Item('bottom-up', 'zh-cn:自底向上; zh-tw:由下而上;'),
Item('Boyce-Codd normal form', 'zh-cn:BC范式; zh-tw:BC正規形式;'),
Item('brain-machine interface', 'zh-cn:脑机接口; zh-my:脑机介面; zh-tw:人機介面;'),
Item('Broadband', 'zh:寬帶; zh-cn:宽带; zh-my:宽频; zh-tw:寬頻;'),
Item('Bubble sort', 'zh-cn:冒泡排序; zh-tw:泡沫排序;'),
Item('buffer', 'zh-cn:缓冲器; zh-tw:緩衝區;'),
Item('buffer overflow', 'zh-cn:缓存溢出; zh-tw:緩衝區溢位;'),
Item('bug', '隐错=>zh-tw:錯誤; 隐错=>zh-hk:錯誤; 隐错=>zh-mo:錯誤;'),
Item('build-in', 'zh:內置; zh-cn:内置; zh-sg:内建; zh-tw:內建;'),
Item('Built-in', '自带=>zh-tw:內建; 自带=>zh-hk:內建; 自带=>zh-mo:內建;'),
Item('Built-in', '自帶=>zh-tw:內建; 自帶=>zh-hk:內建; 自帶=>zh-mo:內建;'),
Item('burn', 'zh-cn:刻录; zh-tw:燒錄;'),
Item('Business Model', 'zh-cn:商业模型; zh-tw:商業模式;'),
Item('Bus', 'zh-cn:总线; zh-tw:匯流排; zh-hk:匯流排;'),
Item('byte', 'zh:字節; zh-cn:字节; zh-tw:位元組; zh-hk:位元組; zh-mo:位元組;'),
Item('boolean', 'zh-cn:布尔; zh-tw:布林;'),
Item('boolean algebra', 'zh-cn:布尔逻辑; zh-tw:布林運算;'),
Item('Boot Camp', 'zh-cn:启动转换; zh-tw:啟動切換; zh-hk:開機切換;'),
{ type = 'text', text = [[
== C ==
]] },
Item('cache', 'zh:緩存; zh-cn:缓存; zh-tw:快取; zh-hk:快取;'),
Item('cache memory', 'zh-cn:缓冲存储器; zh-tw:快取記憶體;'),
Item('cache memory', '缓冲存储器=>zh-hk:緩衝記憶體; 缓冲存储器=>zh-mo:緩衝記憶體;'),
Item('cache memory', '缓存器=>zh-tw:快取記憶體; 缓存器=>zh-hk:緩衝記憶體; 缓存器=>zh-mo:緩衝記憶體;'),
Item('cache memory', '快取記憶體=>zh-hk:緩衝記憶體; 快取記憶體=>zh-mo:緩衝記憶體;'),
Item('cache memory', 'zh-cn:高速缓冲存储器; zh-tw:高速緩衝記憶體;'),
Item('cache memory', '高速缓存=>zh-tw:高速緩衝記憶體; 高速缓存=>zh-hk:高速緩衝記憶體; 高速缓存=>zh-mo:高速緩衝記憶體;'),
Item('cached webpage', 'zh-cn:网页快照; zh-tw:頁庫存檔;'),
Item('calculator', 'zh-cn:计算器; zh-hk:計數機;'),
Item('calculator', '计算器=>zh-tw:計算機;'),
Item('calculator', '計數機=>zh-tw:計算機;'),
Item('calculator', '計算器=>zh-hk:計數機; 計算器=>zh-mo:計數機;'),
Item('calendar', '行事曆=>zh-cn:日历; 行事曆=>zh-sg:日历; 行事曆=>zh-my:日历;'),
Item('calendar program', 'zh-cn:日历程序; zh-tw:行事曆程式;'),
Item('call', 'zh-cn:调用; zh-tw:呼叫;'),
Item('Call Level Interface (CLI)', 'zh-cn:调用层接口; zh-tw:呼叫層級介面;'),
-- 回撥似乎用在電話比較多,計算機上回呼比較多。
Item('callback', 'zh-cn:回调; zh-tw:回呼;'),
Item('camcorder', 'zh-cn:摄像机; zh-tw:攝錄影機; zh-hk:攝像放像機;'),
Item('camera phone', 'zh-cn:照相手机; zh-tw:照相手機; zh-hk:相機手機;'),
Item('campus network', 'zh-cn:校园网; zh-tw:校園網路; zh-hk:校園網絡;'),
Item('campus network', '园区网络=>zh-tw:校園網路; 园区网络=>zh-hk:校園網絡; 园区网络=>zh-mo:校園網絡;'),
Item('capture', '捕获=>zh-tw:擷取; 捕获=>zh-hk:擷取; 捕获=>zh-mo:擷取;'),
Item('card reader', 'zh-cn:读卡器; zh-tw:讀卡機; zh-hk:讀卡器;'),
Item('carriage return character', 'zh-cn:回车符; zh-tw:回車字元;'),
Item('CDN', 'zh-cn:内容分发网络; zh-tw:內容傳遞網路;'),
Item('Cell', 'zh-cn:单元格; zh-tw:儲存格;'),
Item('Cellular data', 'zh-cn:蜂窝数据; zh-tw:蜂巢式資料; zh-hk:蜂巢式數據;'),
Item('Cellular network', 'zh-cn:蜂窝网络; zh-tw:蜂巢式網路; zh-hk:蜂巢式網絡;'),
Item('certificate', 'zh-cn:证书; zh-tw:憑證; zh-hk:證書;'),
Item('chain', '串鏈=>zh-cn:链; 串鏈=>zh-sg:链; 串鏈=>zh-my:链;'),
Item('chaining', '鍊接=>zh-cn:链接; 鍊接=>zh-sg:链接; 鍊接=>zh-my:链接;'),
Item('chaining backward', 'zh-cn:链接反向; zh-tw:鏈結反向;'),
Item('chaining forward', 'zh-cn:链接正向; zh-tw:鏈結正向;'),
Item('chaining of commands', 'zh-cn:命令链接; zh-tw:命令鏈結;'),
Item('chaining search', 'zh-cn:链接搜索; zh-tw:鏈結搜尋;'),
Item('channel', '渠道=>zh-tw:管道;'),
Item('character', 'zh-cn:字符; zh-tw:字元;'),
Item('character generator', 'zh-cn:字符生成器; zh-tw:字元產生器;'),
Item('character printer', 'zh-cn:字符打印机; zh-tw:字元列印機;'),
Item('check bit', 'zh-cn:检验位; zh-tw:核對位元;'),
Item('check button', 'zh-cn:复选按钮; zh-tw:核取按鈕;'),
Item('checkbox', 'zh-cn:复选框; zh-tw:核取方塊;'),
Item('checksum', 'zh-cn:检验和; zh-tw:核對和;'),
Item('Chief Executive Officer (CEO)', 'zh:首席執行官; zh-cn:首席执行官; zh-sg:行政总裁; zh-my:总执行长; zh-tw:執行長; zh-hk:行政總裁;'),
Item('Chief Information Officer (CIO)', 'zh-cn:首席信息官; zh-my:总资讯长; zh-tw:資訊長; zh-hk:資訊總監;'),
Item('Chief Operating Officer (COO)', 'zh:首席運營官; zh-cn:首席运营官; zh-my:总营运长; zh-tw:營運長; zh-hk:營運總監;'),
Item('Chief Technology Officer (CTO)', 'zh:首席技術官; zh-cn:首席技术官; zh-my:总技术长; zh-tw:技術長;'),
Item('child class', '子類別=>zh-cn:子类; 子類別=>zh-sg:子类; 子類別=>zh-my:子类;'),
Item('chip', 'zh-cn:芯片; zh-my:晶片; zh-tw:晶片;'),
Item('class constructor', 'zh-cn:类的构造函数; zh-tw:類別的建構函數;'),
Item('class constructor', '類別建構子=>zh-cn:类的构造函数; 類別建構子=>zh-sg:类的构造函数; 類別建構子=>zh-my:类的构造函数;'),
Item('class declaration', 'zh-cn:类声明; zh-tw:類別宣告;'),
Item('class definition', 'zh-cn:类定义; zh-tw:類別定義;'),
Item('class destructor', 'zh-cn:类的析构函数; zh-tw:類別的破壞函數;'),
Item('class destructor', '類別破壞子=>zh-cn:类的析构函数; 類別破壞子=>zh-sg:类的析构函数; 類別破壞子=>zh-my:类的析构函数;'),
Item('class instance', 'zh-cn:类的实例; zh-tw:類別的實例;'),
Item('class instance', 'zh-cn:类实例; zh-tw:類別實例;'),
Item('class library', 'zh-cn:类库; zh-tw:類別館;'),
Item('class member', 'zh-cn:类成员; zh-tw:類別成員;'),
Item('class method', 'zh-cn:类方法; zh-tw:類別方法;'),
Item('class of C++', 'zh-cn:C++类; zh-tw:C++類別;'),
Item('class of C++', 'zh-cn:C++的类; zh-tw:C++的類別;'),
Item('class of Java', 'zh-cn:Java类; zh-tw:Java類別;'),
Item('class of Java', 'zh-cn:Java的类; zh-tw:Java的類別;'),
Item('class template', 'zh-cn:类模板; zh-tw:類別模板;'),
Item('class variable', 'zh-cn:类变量; zh-tw:類別變數;'),
Item('class-based', 'zh-cn:基于类; zh-tw:類別為基;'),
Item('class-based programming', 'zh-cn:基于类的编程; zh-tw:類別為基的程式設計;'),
Item('class-orientation', 'zh-cn:面向类; zh-tw:類別導向;'),
Item('classloader', 'zh-cn:类加载器; zh-tw:類別載入器;'),
Item('client', '用戶端=>zh-cn:客户端; 用戶端=>zh-sg:客户端; 用戶端=>zh-my:客户端;'),
Item('clipboard', 'zh:剪貼板; zh-cn:剪贴板; zh-my:剪贴簿; zh-tw:剪貼簿;'),
Item('clock rate', 'zh-cn:时钟频率; zh-tw:時脈頻率; zh-hk:時鐘頻率;'),
Item('clock rate', '時脈速率=>zh-cn:时钟频率; 時脈速率=>zh-sg:时钟频率; 時脈速率=>zh-my:时钟频率;'),
-- 国立编译馆的翻译
Item('clock rate', '時鐘率=>zh-cn:时钟频率; 時鐘率=>zh-sg:时钟频率; 時鐘率=>zh-my:时钟频率;'),
-- 容易過度轉換
Item('clock rate', '時脈=>zh-cn:主频;'),
-- 暂先单向转换,请补充
Item('cloud computing', 'zh:雲計算; zh-cn:云计算; zh-tw:雲端運算;'),
Item('cloud computing storage', 'zh-cn:云存储; zh-sg:云储存; zh-my:云端储存; zh-tw:雲端儲存;'),
Item('cluster', 'zh-cn:集群; zh-tw:叢集;'),
Item('cluster', '群集=>zh-cn:聚类; 群集=>zh-sg:聚类; 群集=>zh-my:聚类;'),
Item('code', '程式碼=>zh-cn:代码; 程式碼=>zh-sg:代码; 程式碼=>zh-my:代码;'),
Item('code generator', 'zh-cn:代码生成器; zh-tw:碼產生器;'),
Item('code page', '代码页=>zh-tw:頁碼; 代码页=>zh-hk:頁碼; 代码页=>zh-mo:頁碼;'),
Item('collaboration', 'zh-cn:协作; zh-tw:協同運作;'),
Item('color monitor', '彩屏=>zh-tw:彩色螢幕; 彩屏=>zh-hk:彩色螢幕; 彩屏=>zh-mo:彩色螢幕;'),
Item('combobox', 'zh-cn:组合框; zh-tw:組合方塊;'),
Item('command line', 'zh-hant:命令列;zh-hans:命令行;'),
-- 有可能過度轉換,編輯時須注意
Item('communication', 'zh:通信;zh-hant:通訊;通訊=>zh-cn:通信;'),
Item('Communicating sequential processes', 'zh-cn:通信顺序进程; zh-tw:交談循序程式;'),
Item('community', '社区=>zh-tw:社群;'),
-- 有可能過度轉換,編輯時須注意
Item('compact disc', 'zh:光盤; zh-cn:光盘; zh-sg:光碟; zh-my:光碟; zh-tw:光碟;'),
Item('compact disc', '光碟片=>zh-cn:光盘;'),
Item('Compact Disc Driver', 'zh-cn:光盘驱动器; zh-sg:光碟机; zh-my:光碟机; zh-tw:光碟機;'),
Item('compatible', 'zh-cn:兼容; zh-tw:相容;'),
Item('compatible', '相兼容=>zh-tw:相容; 相兼容=>zh-hk:相容; 相兼容=>zh-mo:相容;'),
Item('complement', '補數=>zh-cn:补码; 補數=>zh-sg:补码; 補數=>zh-my:补码; 補數=>zh-hk:補碼; 補數=>zh-mo:補碼;'),
Item('complexity class', 'zh-cn:复杂性类; zh-tw:複雜性類別;'),
Item('complexity class', 'zh-cn:复杂度类; zh-tw:複雜度類別;'),
Item('component', '元件=>zh-cn:组件; 元件=>zh-sg:组件; 元件=>zh-my:组件;'),
Item('computer', '计算机=>zh-sg:电脑; 计算机=>zh-my:电脑; 计算机=>zh-tw:電腦; 计算机=>zh-hk:電腦; 计算机=>zh-mo:電腦;'),
Item('computer', '計算機=>zh-sg:电脑; 計算機=>zh-my:电脑;'),
Item('computer', '电子计算机=>zh-sg:电脑; 电子计算机=>zh-my:电脑; 电子计算机=>zh-tw:電腦; 电子计算机=>zh-hk:電腦; 电子计算机=>zh-mo:電腦;'),
Item('computer', '電子計算機=>zh-cn:电子计算机; 電子計算機=>zh-sg:电脑; 電子計算機=>zh-my:电脑;'),
Item('computer architecture', 'zh:計算機體系結構; zh-cn:计算机体系结构; zh-sg:电脑架构; zh-my:电脑架构; zh-tw:電腦架構;'),
Item('computer programming', 'zh:程序設計; zh-cn:程序设计; zh-my:程式设计; zh-tw:程式設計;'),
Item('computer science', 'zh:計算機科學; zh-cn:计算机科学; zh-my:电脑科学; zh-tw:電腦科學;'),
Item('computer terminal', '終端機=>zh-cn:终端; 終端機=>zh-sg:终端; 終端機=>zh-my:终端;'),
Item('computer-generated imagery', 'zh:電腦產生圖像; zh-cn:电脑产生图像; zh-sg:电脑合成影像; zh-my:电脑合成影像; zh-hant:電腦合成影像;'),
Item('concurrency', 'zh-cn:并发; zh-tw:並行;'),
Item('concurrent computing', 'zh-cn:并发计算; zh-tw:並行計算;'),
Item('concurrency-oriented', 'zh-cn:面向并发; zh-tw:平行導向;'),
Item('configure/configuration', 'zh-cn:配置; zh-tw:組態;'),
Item('configuration files', 'zh-cn:配置文件; zh-tw:組態檔;'),
-- Item('connection', 'zh-cn:连接; zh-tw:連線;'), 容易過度轉換
Item('constant', 'zh-cn:常量; zh-tw:常數;'),
Item('constant bitrate', 'zh-cn:固定码率; zh-tw:固定位元速率;'),
Item('constructor', 'zh-cn:构造函数; zh-tw:建構函式;'),
Item('constructor', '建構函數=>zh-cn:构造函数; 建構函數=>zh-tw:建構函式;'),
Item('constructor', '建構子=>zh-cn:构造函数; 建構子=>zh-sg:构造函数; 建構子=>zh-my:构造函数;'),
Item('contact', 'zh-cn:联系; zh-my:联络; zh-tw:聯絡; 連絡=>zh-cn:联系;'),
Item('contact', 'zh:聯繫人; zh-cn:联系人; zh-my:联络人; zh-tw:聯絡人;'),
Item('content-addressable memory', 'zh-cn:内容可寻址存储器; zh-tw:可定址內容記憶體;'),
Item('content-addressable memory', 'zh-cn:结合存储; zh-tw:可定址內容記憶體;'),
Item('context switch', 'zh-cn:上下文切换; zh-tw:上下文交換;'),
Item('Continuity', 'zh-cn:连续互通; zh-tw:接續互通;'),
Item('control', 'zh-cn:控件; zh-tw:控制項;'),
Item('convert', '轉檔=>zh-cn:转换; 轉檔=>zh-sg:转换; 轉檔=>zh-my:转换;'),
Item('copper clad laminate', 'zh-cn:覆铜板; zh-tw:銅箔基板;'),
Item('copyright', 'zh:版权; zh-cn:著作权; zh-tw:著作權; zh-hk:版權; zh-mo:著作權;'),
Item('copyright information', '版权信息=>zh-cn:著作权信息; 版权信息=>zh-sg:著作权信息; 版权信息=>zh-my:著作权信息; 版权信息=>zh-tw:著作權資訊; 版权信息=>zh-mo:著作權資訊;'),
Item('cost-effective', 'zh-cn:性价比; zh-tw:CP值; zh-hk:性價比;'),
Item('cracker', 'zh-cn:溃客; zh-tw:劊客; zh-hk:潰客;'),
Item('crash', 'zh-hk:死機; zh-cn:死机; zh-my:当机; zh-sg:当机; zh-tw:當機;'),
Item('create', 'zh:创建; zh-tw:建立;'),
Item('create', '創建=>zh-tw:建立;'),
Item('create new', 'zh:创建新; zh-tw:新增;'),
Item('create new', '創建新=>zh-tw:新增;'),
Item('CRT', 'zh-cn:显像管; zh-tw:映像管; zh-hk:顯像管;'),
Item('current version', 'zh-cn:当前版本; zh-tw:目前版本;'),
Item('cursor', 'zh-cn:光标; zh-tw:游標;'),
Item('custom', 'zh-cn:自定义; zh-tw:自訂;'),
Item('custom', '自定義=>zh-tw:自訂; 自定義=>zh-hk:自訂; 自定義=>zh-mo:自訂;'),
Item('custom', '自定=>zh-tw:自訂; 自定=>zh-hk:自訂; 自定=>zh-mo:自訂;'),
Item('customization', 'zh-cn:定制; zh-tw:客製化;'),
Item('cut', 'zh-cn:剪切; zh-tw:剪下;'),
Item('cyberbullying', 'zh-cn:网络欺凌; zh-tw:網路霸凌; zh-hk:網上欺凌;'),
Item('Cyber-Physical System', 'zh-cn:信息物理系统; zh-tw:網宇實體系統;'),
{ type = 'text', text = [[
== D ==
]] },
Item('daemon', 'zh-cn:守护进程; zh-tw:守護行程;'),
Item('daisy chaining', 'zh-cn:菊花链接; zh-tw:菊式鏈結;'),
Item('data', '数据=>zh-tw:資料; 数据=>zh-hk:數據;'),
Item('database', 'zh-cn:数据库; zh-tw:資料庫; zh-hk:資料庫;'),
Item('data center', 'zh-cn:数据中心; zh-hk:數據中心; zh-tw:資料中心;'),
Item('data chaining', 'zh-cn:数据链接; zh-tw:資料鏈結;'),
Item('data cleansing', 'zh-cn:数据清洗; zh-tw:資料淨化;'),
Item('data dredging', 'zh-cn:数据捕捞; zh-tw:資料挖掘; zh-hk:數據捕撈;'),
Item('data execution protection', 'zh-cn:数据执行保护; zh-tw:系統記憶體保護; zh-hk:數據執行保護;'),
Item('data frame', 'zh-cn:数据帧; zh-tw:資料訊框; zh-hk:數據幀;'),
Item('data mart', 'zh-cn:数据集市; zh-tw:資料市集; zh-hk:數據市集;'),
Item('data mining', 'zh-cn:数据挖掘; zh-tw:資料探勘; zh-hk:數據探勘;'),
Item('data packet', 'zh:數據包; zh-cn:数据包; zh-tw:封包;'),
Item('data packet', '数据封包=>zh-cn:数据包; 數據封包=>zh-cn:数据包; 資料封包=>zh-cn:数据包;'),
Item('data source', '数据源=>zh-cn:数据源; 数据源=>zh-tw:資料來源; 数据源=>zh-hk:數據源;'),
Item('data type', 'zh-cn:数据类型; zh-hant:資料類型;'),
Item('data warehouse', 'zh-cn:数据仓库; zh-tw:資料倉儲; zh-hk:數據倉庫;'),
Item('datagram', 'zh-cn:数据报文;zh-tw:資料報;'),
Item('deadlock', 'zh-cn:死锁; zh-tw:死結;'),
Item('debug', 'zh-cn:调试; zh-tw:除錯;'),
Item('debug', '除错=>zh-cn:调试; 除错=>zh-sg:调试; 除错=>zh-my:调试;'),
Item('debug', '偵錯=>zh-cn:调试; 偵錯=>zh-sg:调试; 偵錯=>zh-my:调试;'),
Item('debug', '侦错=>zh-cn:调试; 侦错=>zh-sg:调试; 侦错=>zh-my:调试;'),
Item('debug', '調試=>zh-tw:除錯; 調試=>zh-hk:除錯; 調試=>zh-mo:除錯;'),
Item('declaration', '声明语句=>zh-tw:宣告; 声明语句=>zh-hk:宣告; 声明语句=>zh-mo:宣告;'),
Item('decode', '译码=>zh-tw:解碼;译码=>zh-sg:解码;译码=>zh-my:解码;'),
Item('default', 'zh-cn:默认; zh-tw:預設;'),
Item('default', '缺省=>zh-tw:預設; 缺省=>zh-hk:預設; 缺省=>zh-mo:預設;'),
Item('definition', '清晰度=>zh-tw:解析度;'),
Item('defragmentation program', 'zh-cn:磁盘碎片整理程序; zh-tw:磁碟重組工具;'),
Item('defragmentation', 'zh-cn:磁盘碎片整理; zh-tw:磁碟重組;'),
Item('denial-of-service (DoS)', 'zh-cn:拒绝服务; zh-tw:阻斷服務;'),
Item('denormalization', 'zh-cn:反规范化; zh-tw:解除規格化;'),
Item('dependent type', 'zh-cn:依赖类型; zh-tw:依值型別;'),
Item('dependent type', 'zh-cn:依存类型; zh-tw:依存型別;'),
Item('derivation list', 'zh-cn:继承列表; zh-tw:衍化列;'),
Item('derive', 'zh-cn:派生; zh-tw:衍生;'),
Item('derived class', 'zh-cn:派生类; zh-tw:衍生類別;'),
Item('derived type', 'zh-cn:派生类型; zh-tw:衍生類型;'),
Item('desktop', 'zh-cn:桌面型; zh-tw:桌上型;'),
Item('desktop computer', 'zh-cn:台式机; zh-sg:台式电脑; zh-my:台式电脑; zh-tw:桌上型電腦; zh-hk:桌上電腦;'),
Item('desktop computer', '桌上型电脑=>zh-cn:台式机; 桌上型电脑=>zh-sg:台式电脑; 桌上型电脑=>zh-my:台式电脑; 桌上型电脑=>zh-hk:桌上電腦; 桌上型电脑=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上电脑=>zh-cn:台式机; 桌上电脑=>zh-sg:台式电脑; 桌上电脑=>zh-my:台式电脑; 桌上电脑=>zh-tw:桌上型電腦;'),
Item('desktop computer', '台式機=>zh-tw:桌上型電腦; 台式機=>zh-hk:桌上電腦; 台式機=>zh-mo:桌上電腦;'),
Item('desktop computer', '臺式機=>zh-tw:桌上型電腦; 臺式機=>zh-hk:桌上電腦; 臺式機=>zh-mo:桌上電腦;'),
Item('desktop computer', '台式计算机=>zh-tw:桌上型電腦; 台式计算机=>zh-hk:桌上電腦; 台式计算机=>zh-mo:桌上電腦;'),
Item('desktop computer', '台式電腦=>zh-tw:桌上型電腦; 台式電腦=>zh-hk:桌上電腦; 台式電腦=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上型计算机=>zh-hk:桌上電腦; 桌上型计算机=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上型計算機=>zh-hk:桌上電腦; 桌上型計算機=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上計算機=>zh-tw:桌上型電腦;'),
Item('desktop version', '桌面版=>zh-tw:電腦版; 桌面版=>zh-hk:電腦版; 桌面版=>zh-mo:電腦版;'),
Item('destruct', 'zh-cn:析构; zh-tw:解構;'),
Item('destructor', 'zh-cn:析构函数; zh-tw:解構函式;'),
Item('destructor', '解構函數=>zh-cn:析构函数; 解構函數=>zh-tw:解構函式;'),
Item('destructor', '解構子=>zh-cn:析构函数; 解構子=>zh-sg:析构函数; 解構子=>zh-my:析构函数;'),
Item('device', 'zh:設備; zh-cn:设备; zh-sg:装置; zh-hant:裝置;'),
Item('dialog box', 'zh-cn:对话框; zh-tw:對話方塊;'),
Item('digital', '数码=>zh-tw:數位; 数码=>zh-sg:数码; 数码=>zh-my:数码;'),
Item('digital', '數碼=>zh-cn:数字; 數碼=>zh-sg:数码; 數碼=>zh-my:数码; 數碼=>zh-tw:數位;'),
Item('digital', '数位=>zh-sg:数码; 数位=>zh-my:数码; 数位=>zh-hk:數碼; 数位=>zh-mo:數碼;'),
Item('digital', '數位=>zh-cn:数字; 數位=>zh-sg:数码; 數位=>zh-my:数码; 數位=>zh-hk:數碼; 數位=>zh-mo:數碼;'),
Item('digital', 'zh:數字圖像; zh-cn:数字图像; zh-sg:数码图像; zh-tw:數位影像; zh-hk:數碼圖像;'),
Item('digitalisation', 'zh:數字化; zh-cn:数字化; zh-sg:数码化; zh-my:数码化; zh-tw:數位化; zh-hk:數碼化;'),
Item('digital asset', 'zh:數字資產; zh-cn:数字资产; zh-sg:数码资产; zh-tw:數位資產; zh-hk:數碼資產;'),
Item('digital broadcasting', 'zh:數字廣播; zh-cn:数字广播; zh-sg:数码广播; zh-my:数码广播; zh-tw:數位廣播; zh-hk:數碼廣播;'),
Item('digital camera', 'zh-cn:数字相机; zh-sg:数码相机; zh-my:数码相机; zh-tw:數位相機; zh-hk:數碼相機;'),
Item('digital certificates', 'zh:數字證書; zh-cn:数字证书; zh-sg:数码证书; zh-tw:數位憑證; zh-hk:數碼證書;'),
Item('digital distribution', 'zh:數字發行; zh-cn:数字发行; zh-sg:数码发行; zh-tw:數位發行; zh-hk:數碼發行;'),
Item('digital identity', 'zh-cn:数字身份; zh-sg:数码身份; zh-my:数码身份; zh-tw:數位身分; zh-hk:數碼身份;'),
Item('digital mapping', 'zh-cn:数字测图; zh-my:数码测图; zh-sg:数码制图; zh-tw:數位製圖; zh-hk:數碼製圖;'),
Item('digital media', 'zh:數字媒體; zh-cn:数字媒体; zh-sg:数码媒体; zh-my:数码媒体; zh-tw:數位媒體; zh-hk:數碼媒體;'),
Item('digital mobile', 'zh-cn:数字移动; zh-sg:数码移动; zh-my:数码移动; zh-tw:數位行動; zh-hk:數碼流動;'),
Item('digital mode', 'zh-cn:数字模式; zh-sg:数码模式; zh-my:数码模式; zh-tw:數位模式; zh-hk:數碼模式;'),
Item('digital photo', 'zh-cn:数字照片; zh-sg:数码照片; zh-my:数码相片; zh-tw:數位相片; zh-hk:數碼相片;'),
Item('digital right', 'zh:數字版權; zh-cn:数字版权; zh-my:数码版权; zh-tw:數位版權; zh-hk:數碼版權;'),
Item('digital signature', 'zh:數字簽名; zh-cn:数字签名; zh-sg:数码签名; zh-my:数码签名; zh-tw:數位簽章; zh-hk:數碼簽章;'),
Item('digital television', 'zh:數字電視; zh-cn:数字电视; zh-sg:数码电视; zh-my:数码电视; zh-tw:數位電視; zh-hk:數碼電視;'),
Item('digital terrestrial television', 'zh:數字地面電視;zh-tw:無線數位電視;zh-sg:地面数码电视;zh-my:地面数码电视;zh-hk:地面數碼電視;zh-mo:數碼地面電視;zh-cn:数字地面电视;'), -- 次常用
Item('digital terrestrial television', 'zh:无线数字电视;zh-tw:數位無線電視;zh-sg:数码地面电视;zh-my:数码地面电视;zh-hk:數碼地面電視;zh-mo:地面數字電視;zh-cn:地面数字电视;'), -- 最常用
Item('digital video', 'zh:數字視頻; zh-cn:数字视频; zh-sg:数码视频; zh-my:数码影音; zh-tw:數位影片; zh-hk:數碼影片;'),
Item('digital video', '視像=>zh-tw:視訊; 視像=>zh-cn:视频; 視像=>zh-my:视频; 視像=>zh-sg:视频;'),
Item('digital video', '视像=>zh-tw:視訊; 视像=>zh-cn:视频; 视像=>zh-my:视频; 视像=>zh-sg:视频;'),
Item('digital video', '視頻=>zh-tw:影片; 視頻=>zh-hk:影片; 視頻=>zh-mo:影片;'),
Item('digital video', '视频=>zh-tw:影片; 视频=>zh-hk:影片; 视频=>zh-mo:影片;'),
Item('digital video', '視訊=>zh-hk:視像; 視訊=>zh-mo:視像; 視訊=>zh-cn:视频; 視訊=>zh-my:视频; 視訊=>zh-sg:视频;'),
Item('digital video', '视讯=>zh-mo:視像; 视讯=>zh-hk:視像; 视讯=>zh-cn:视频; 视讯=>zh-my:视频; 视讯=>zh-sg:视频;'),
Item('digital video', 'zh-cn:监控; zh-tw:監視; zh-hk:監視;'),
Item('digital watermarking', 'zh-cn:数字水印; zh-my:数码水印; zh-sg:数码水印; zh-tw:數位浮水印; zh-hk:數碼水印;'),
Item('disk', 'zh:磁盤; zh-cn:磁盘; zh-my:磁碟; zh-tw:磁碟;'),
Item('display device', '显示屏=>zh-tw:顯示器; 显示屏=>zh-hk:顯示器; 显示屏=>zh-mo:顯示器;'),
Item('display memory', 'zh-cn:显示内存; zh-tw:顯示記憶體;'),
Item('distributed', 'zh-cn:分布式; zh-tw:分散式;'),
Item('document', '文档=>zh-tw:文件; 文档=>zh-hk:文件; 文档=>zh-mo:文件;'), --容易过度转换,实际均存在互用的情况
Item('document', '文檔=>zh-tw:文件; 文檔=>zh-hk:文件; 文檔=>zh-mo:文件;'),
Item('document file', 'zh-cn:文档文件; zh-tw:文件檔案;'), --需要确认
Item('document file', '文件檔=>zh-cn:文档文件; 文件檔=>zh-sg:文档文件; 文件檔=>zh-my:文档文件;'),
Item('document-oriented', 'zh-cn:面向文档; zh-tw:文件導向;'),
Item('document object model (DOM)', 'zh-cn:文档对象模型; zh-tw:文件物件模型;'),
Item('do Not Track', 'zh-cn:请勿追踪; zh-tw:停止追蹤;'),
Item('domain-key normal form', 'zh-cn:DK范式; zh-tw:DK規格化;'),
Item('drive', 'zh-cn:磁盘驱动器; zh-tw:磁碟機;'),
Item('drive - A drive', 'zh-cn:A盘; zh-tw:本機磁碟(A); zh-hk:A磁碟機;'),
Item('drive - B drive', 'zh-cn:B盘; zh-tw:本機磁碟(B); zh-hk:B磁碟機;'),
Item('drive - C drive', 'zh-cn:C盘; zh-tw:本機磁碟(C); zh-hk:C磁碟機;'),
Item('drive - D drive', 'zh-cn:D盘; zh-tw:本機磁碟(D); zh-hk:D磁碟機;'),
Item('drive - E drive', 'zh-cn:E盘; zh-tw:本機磁碟(E); zh-hk:E磁碟機;'),
Item('drive - F drive', 'zh-cn:F盘; zh-tw:本機磁碟(F); zh-hk:F磁碟機;'),
Item('drive - G drive', 'zh-cn:G盘; zh-tw:本機磁碟(G); zh-hk:G磁碟機;'),
Item('drive - H drive', 'zh-cn:H盘; zh-tw:本機磁碟(H); zh-hk:H磁碟機;'),
Item('drive - I drive', 'zh-cn:I盘; zh-tw:本機磁碟(I); zh-hk:I磁碟機;'),
Item('drive - J drive', 'zh-cn:J盘; zh-tw:本機磁碟(J); zh-hk:J磁碟機;'),
Item('drive - K drive', 'zh-cn:K盘; zh-tw:本機磁碟(K); zh-hk:K磁碟機;'),
Item('drive - L drive', 'zh-cn:L盘; zh-tw:本機磁碟(L); zh-hk:L磁碟機;'),
Item('drive - M drive', 'zh-cn:M盘; zh-tw:本機磁碟(M); zh-hk:M磁碟機;'),
Item('drive - N drive', 'zh-cn:N盘; zh-tw:本機磁碟(N); zh-hk:N磁碟機;'),
Item('drive - O drive', 'zh-cn:O盘; zh-tw:本機磁碟(O); zh-hk:O磁碟機;'),
Item('drive - P drive', 'zh-cn:P盘; zh-tw:本機磁碟(P); zh-hk:P磁碟機;'),
Item('drive - Q drive', 'zh-cn:Q盘; zh-tw:本機磁碟(Q); zh-hk:Q磁碟機;'),
Item('drive - R drive', 'zh-cn:R盘; zh-tw:本機磁碟(R); zh-hk:R磁碟機;'),
Item('drive - S drive', 'zh-cn:S盘; zh-tw:本機磁碟(S); zh-hk:S磁碟機;'),
Item('drive - T drive', 'zh-cn:T盘; zh-tw:本機磁碟(T); zh-hk:T磁碟機;'),
Item('drive - U drive', 'U磁碟機=>zh-cn:U盘; U磁碟機=>zh-sg:U盘; U磁碟機=>zh-my:U盘; U磁碟機=>zh-tw:USB磁碟機;'),
-- U盘與USB flash drive有衝突
Item('drive - U drive', 'U槽=>zh-cn:U盘; U槽=>zh-sg:U盘; U槽=>zh-my:U盘; U槽=>zh-tw:USB磁碟機; U槽=>zh-hk:U磁碟機; U槽=>zh-mo:U磁碟機;'),
Item('drive - V drive', 'zh-cn:V盘; zh-tw:本機磁碟(V); zh-hk:V磁碟機;'),
Item('drive - W drive', 'zh-cn:W盘; zh-tw:本機磁碟(W); zh-hk:W磁碟機;'),
Item('drive - X drive', 'zh-cn:X盘; zh-tw:本機磁碟(X); zh-hk:X磁碟機;'),
Item('drive - Y drive', 'zh-cn:Y盘; zh-tw:本機磁碟(Y); zh-hk:Y磁碟機;'),
Item('drive - Z drive', 'zh-cn:Z盘; zh-tw:本機磁碟(Z); zh-hk:Z磁碟機;'),
Item('drive - system drive', 'zh-cn:系统盘; zh-tw:系統磁碟; zh-hk:系統磁碟機;'),
Item('drive letter', 'zh-cn:盘符; zh-tw:磁碟機代號;'),
Item('driver', 'zh:驅動程序; zh-cn:驱动程序; zh-my:驱动程式; zh-tw:驅動程式;'),
Item('drop-down menu', 'zh-cn:下拉菜单; zh-tw:下拉式選單;'),
Item('Dual-link', 'zh-cn:双通道; zh-tw:雙連結;'),
Item('duck typing', 'zh-cn:鸭子类型; zh-tw:鴨子型別;'),
Item('dynamic binding', 'zh-cn:动态绑定; zh-tw:動態繫結;'),
Item('dynamic typing', 'zh-cn:动态类型; zh-tw:動態型別;'),
{ type = 'text', text = [[
== E ==
]] },
Item('edit bar', 'zh-cn:编辑栏; zh-tw:編輯列;'),
Item('email', '电子邮件=>zh-sg:电邮; 电子邮件=>zh-my:电邮;'),
Item('email', '電子郵件=>zh-sg:电邮; 電子郵件=>zh-my:电邮;'),
Item('email', '电邮=>zh-tw:電子郵件;'),
Item('email', '電郵=>zh-tw:電子郵件;'),
Item('email', '电子信件=>zh-cn:电子邮件; 电子信件=>zh-sg:电邮; 电子信件=>zh-my:电邮; 电子信件=>zh-tw:電子郵件;'),
Item('email', '電子信件=>zh-cn:电子邮件; 電子信件=>zh-sg:电邮; 電子信件=>zh-my:电邮; 電子信件=>zh-tw:電子郵件;'),
Item('email (mailbox)', 'zh-cn:邮箱; zh-tw:電子信箱; zh-hk:郵箱;'),
Item('email (mailbox)', '电子邮箱=>zh-tw:電子信箱;'),
Item('email (mailbox)', '電子郵箱=>zh-tw:電子信箱;'),
Item('enclosed', '带圈=>zh-tw:圍繞; 带圈=>zh-hk:圍繞; 带圈=>zh-mo:圍繞;'),
Item('enclosed', '帶圈=>zh-tw:圍繞; 帶圈=>zh-hk:圍繞; 帶圈=>zh-mo:圍繞;'),
Item('enclosed character', 'zh-cn:带圈字符; zh-tw:圍繞字元;'),
Item('end user', 'zh-cn:最终用户; zh-tw:終端使用者;'),
Item('end-user license agreements', 'zh-cn:最终用户许可协议; zh-tw:終端使用者授權協定;'),
Item('enter', '回车=>zh-tw:Enter; 回车=>zh-hk:Enter; 回车=>zh-mo:Enter;'),
Item('enter key', 'zh:回車鍵; zh-cn:回车键; zh-sg:确认键; zh-my:确认键; zh-tw:確認鍵;'),
Item('enumeration', 'zh-cn:枚举; zh-tw:列舉;'),
Item('enumerators', 'zh-cn:枚举器; zh-tw:列舉元;'),
Item('enumerators', 'zh-cn:枚举成员; zh-tw:列舉元;'),
Item('escape', 'zh-cn:转义; zh-tw:跳脫;'),
Item('Ethernet', 'zh-cn:以太网; zh-tw:乙太網路;'),
Item('Ethernet', '以太网络 => zh-tw:乙太網路;'),
Item('EULA', 'zh-cn:最终用户许可协议; zh-tw:終端使用者授權合約;'),
Item('Exabyte', 'zh-hans:艾字节; zh-hant:艾位元組;'),
Item('exception handling', 'zh-cn:异常处理; zh-tw:例外處理;'),
Item('exclusive or', 'zh-cn:异或; zh-tw:互斥或; zh-hk:異或;'),
Item('executable file', '可执行文件=>zh-tw:可執行檔;'),
Item('executable file', '執行檔=>zh-cn:可执行文件; 執行檔=>zh-sg:可执行文件; 執行檔=>zh-my:可执行文件;'),
-- Item('exit/quit', 'zh-cn:退出; zh-tw:結束;'), 容易過度轉換
Item('exit/quit application', 'zh-cn:退出程序; zh-tw:結束程式;'),
Item('exit/quit application', 'zh-cn:退出应用程序; zh-tw:結束應用程式; zh-hk:結束應用程序;'),
Item('expand', 'zh-cn:扩展; zh-tw:擴充;'),
Item('export', 'zh-cn:导出; zh-tw:匯出;'),
Item('expression', '運算式=>zh-cn:表达式; 運算式=>zh-sg:表达式; 運算式=>zh-my:表达式;'),
Item('extended block', '扩充区=>zh-cn:扩展区; 扩充区=>zh-sg:扩展区; 扩充区=>zh-my:扩展区;'),
Item('extended block', '擴展區=>zh-tw:擴充區; 擴展區=>zh-hk:擴充區; 擴展區=>zh-mo:擴充區;'),
Item('extended Chinese character', '扩充汉字=>zh-cn:扩展汉字;'),
Item('extended Chinese character', 'zh:擴展漢字; zh-hant:擴充漢字;'),
Item('extended reality', 'zh-cn:扩展现实; zh-tw:延展實境;'),
Item('extensible', 'zh:可擴展; zh-cn:可扩展; zh-tw:可延伸;'),
Item('extensible business reporting language', 'zh-cn:可扩展商业报告语言; zh-tw:可延伸商用報告語言;'),
Item('extensible firmware interface', 'zh-cn:可扩展固件接口; zh-tw:可延伸韌體介面;'),
Item('extensible markup language', 'zh-cn:可扩展置标语言; zh-tw:可延伸標示語言;'),
Item('extension name', 'zh-cn:扩展名; zh-tw:副檔名;'),
Item('extension', '擴充套件=>zh-cn:扩展; 擴充套件=>zh-sg:扩展; 擴充套件=>zh-my:扩展;'),
Item('extension', '擴充功能=>zh-cn:扩展; 擴充功能=>zh-sg:扩展; 擴充功能=>zh-my:扩展;'),
Item('extension A', '扩充A区=>zh-cn:扩展A区; 扩充A区=>zh-sg:扩展A区; 扩充A区=>zh-my:扩展A区;'),
Item('extension A', '擴展A區=>zh-tw:擴充A區; 擴展A區=>zh-hk:擴充A區; 擴展A區=>zh-mo:擴充A區;'),
Item('extension B', '扩充B区=>zh-cn:扩展B区; 扩充B区=>zh-sg:扩展B区; 扩充B区=>zh-my:扩展B区;'),
Item('extension B', '擴展B區=>zh-tw:擴充B區; 擴展B區=>zh-hk:擴充B區; 擴展B區=>zh-mo:擴充B區;'),
Item('extension C', '扩充C区=>zh-cn:扩展C区; 扩充C区=>zh-sg:扩展C区; 扩充C区=>zh-my:扩展C区;'),
Item('extension C', '擴展C區=>zh-tw:擴充C區; 擴展C區=>zh-hk:擴充C區; 擴展C區=>zh-mo:擴充C區;'),
Item('extension D', '扩充D区=>zh-cn:扩展D区; 扩充D区=>zh-sg:扩展D区; 扩充D区=>zh-my:扩展D区;'),
Item('extension D', '擴展D區=>zh-tw:擴充D區; 擴展D區=>zh-hk:擴充D區; 擴展D區=>zh-mo:擴充D區;'),
Item('extension E', '扩充E区=>zh-cn:扩展E区; 扩充E区=>zh-sg:扩展E区; 扩充E区=>zh-my:扩展E区;'),
Item('extension E', '擴展E區=>zh-tw:擴充E區; 擴展E區=>zh-hk:擴充E區; 擴展E區=>zh-mo:擴充E區;'),
Item('extension F', '扩充F区=>zh-cn:扩展F区; 扩充F区=>zh-sg:扩展F区; 扩充F区=>zh-my:扩展F区;'),
Item('extension F', '擴展F區=>zh-tw:擴充F區; 擴展F區=>zh-hk:擴充F區; 擴展F區=>zh-mo:擴充F區;'),
Item('extension G', '扩充G区=>zh-cn:扩展G区; 扩充G区=>zh-sg:扩展G区; 扩充G区=>zh-my:扩展G区;'),
Item('extension G', '擴展G區=>zh-tw:擴充G區; 擴展G區=>zh-hk:擴充G區; 擴展G區=>zh-mo:擴充G區;'),
Item('external hard drive', 'zh-cn:外置硬盘; zh-tw:外接硬碟;'),
Item('external link', '外链=>zh-tw:外部連結; 外链=>zh-hk:外部連結; 外链=>zh-mo:外部連結;'),
Item('external link', '外鏈=>zh-tw:外部連結; 外鏈=>zh-hk:外部連結; 外鏈=>zh-mo:外部連結;'),
Item('enterprise mobility management', 'zh-cn:企业移动管理; zh-tw:企業行動管理;'),
{ type = 'text', text = [[
== F ==
]] },
Item('Facebook', 'zh-cn:脸谱; zh-sg:面簿; zh-my:脸书; zh-tw:臉書;'),
Item('Facebook', '脸谱=>zh-hk:Facebook; 臉譜=>zh-hk:Facebook; 面簿=>zh-hk:Facebook; 脸书=>zh-hk:Facebook; 臉書=>zh-hk:Facebook; 面书=>zh-hk:Facebook; 面書=>zh-hk:Facebook; 脸谱=>zh-mo:Facebook; 臉譜=>zh-mo:Facebook; 面簿=>zh-mo:Facebook; 脸书=>zh-mo:Facebook; 臉書=>zh-mo:Facebook; 面书=>zh-mo:Facebook; 面書=>zh-mo:Facebook;'),
Item('facial recognition', 'zh-cn:人脸识别; zh-tw:臉部辨識; zh-hk:人面辨識;'),
Item('facial recognition', '人臉辨識=>zh-tw:臉部辨識;人臉辨識=>zh-hk:人面辨識;人臉辨識=>zh-mo:人面辨識;'),
Item('fairchild semiconductor', 'zh-cn:仙童半导体;zh-hans:飞兆半导体; zh-tw:快捷半導體;'),
Item('feature phone', 'zh-cn:功能手机; zh-tw:功能型手機; zh-hk:功能電話;'),
Item('feedback', 'zh-cn:反馈; zh-tw:回饋; zh-hk:反饋;'),
Item('fiber distributed data interface', 'zh-cn:光纤分布式数据接口; zh-tw:光纖分散式資料介面; zh-hk:光纖分散式數據介面;'),
Item('field', 'zh-cn:字段; zh-tw:欄位;'),
Item('fifth normal form', 'zh-cn:第五范式; zh-tw:第五規格化;'),
Item('file', 'zh-cn:文件; zh-tw:檔案;'), --容易过度转换,实际均存在互用的情况
Item('dile descriptor', 'zh-cn:文件描述符; zh-hant:檔案描述子;'),
Item('File namespace', 'zh-cn:文件命名空间; zh-tw:檔案命名空間;'),
Item('filename', 'zh-cn:文件名; zh-tw:檔名;'),
Item('filename', 'zh:文件名稱; zh-cn:文件名称; zh-tw:檔案名稱;'),
Item('filename', 'zh-cn:文件名字; zh-tw:檔案名字;'),
Item('filename extension', 'zh-cn:文件扩展名; zh-tw:副檔名;'),
Item('filename extension', 'zh-cn:扩展名; zh-tw:副檔名;'),
Item('film streaming', 'zh-cn:影片流; zh-tw:影片串流;'),
Item('find', 'zh-cn:查找; zh-tw:尋找;'),
Item('firmware', 'zh-cn:固件; zh-tw:韌體;'),
Item('first normal form', 'zh-cn:第一范式; zh-tw:第一規格化;'),
Item('flash memory', 'zh-cn:闪存; zh-tw:快閃記憶體;'),
Item('flight mode', 'zh-cn:飞行模式; zh-tw:飛航模式;'),
Item('floppy disk', 'zh:軟盤; zh-cn:软盘; zh-sg:软碟; zh-tw:軟碟;'),
Item('floppy disk drive', 'zh-cn:软盘驱动器; zh-tw:軟碟機;'),
Item('folder', 'zh:文件夾; zh-cn:文件夹; zh-tw:資料夾;'),
Item('font', 'zh-cn:字体; zh-tw:字型;'),
Item('footer', 'zh-cn:页脚; zh-tw:頁尾;'),
Item('footnote', 'zh-cn:脚注; zh-tw:註腳;'),
Item('footnote', 'zh-cn:尾注; zh-tw:章節附註;'),
Item('foreign key', 'zh-cn:外键; zh-tw:外來鍵;'),
Item('form', 'zh-cn:窗体; zh-tw:表單;'),
Item('forward chaining', 'zh-cn:前向链接; zh-tw:正向鏈結;'),
Item('forward error correction', 'zh-cn:前向纠错; zh-tw:正向錯誤校正;'),
Item('fourth normal form', 'zh-cn:第四范式; zh-tw:第四規格化;'),
Item('frame', 'zh-cn:帧; zh-tw:訊框; zh-hk:幀;'),
Item('frame', '片格=>zh-cn:帧; 片格=>zh-sg:帧; 片格=>zh-my:帧; 片格=>zh-hk:幀; 片格=>zh-mo:幀;'),
Item('frame', '讯框=>zh-cn:帧; 讯框=>zh-sg:帧; 讯框=>zh-my:帧; 讯框=>zh-hk:幀; 讯框=>zh-mo:幀;'),
Item('frame', '影格=>zh-cn:帧; 影格=>zh-sg:帧; 影格=>zh-my:帧; 影格=>zh-hk:幀; 影格=>zh-mo:幀;'),
Item('frame', '畫格=>zh-cn:帧; 畫格=>zh-sg:帧; 畫格=>zh-my:帧; 畫格=>zh-hk:幀; 畫格=>zh-mo:幀;'),
Item('frame rate', 'zh-cn:帧率; zh-tw:影格率; zh-hk:幀率;'),
Item('frame rate', '影格速率=>zh-cn:帧率; 影格速率=>zh-sg:帧率; 影格速率=>zh-my:帧率; 影格速率=>zh-hk:幀率; 影格速率=>zh-mo:幀率;'),
Item('frame pointer', 'zh-cn:帧指针; zh-tw:影格指標; zh-hk:框指標;'),
Item('frame synchronization', 'zh-cn:帧同步; zh-tw:影格同步化; zh-hk:框同步化;'),
Item('forum', 'zh-cn:论坛; zh-tw:論壇; zh-hk:討論區;'),
Item('full screen', 'zh-cn:全屏; zh-tw:全螢幕; zh-hk:全螢幕;'),
Item('full screen', '全面屏=>zh-tw:全螢幕; 全面屏=>zh-hk:全螢幕; 全面屏=>zh-mo:全螢幕;'),
Item('full-size smartphone', 'zh-cn:全面屏手机; zh-tw:全螢幕手機; zh-hk:全螢幕手機;'),
Item('fullwidth', 'zh-cn:全角; zh-tw:全形;'),
Item('function', 'zh-cn:函数; zh-tw:函式; zh-hk:函數;'),
-- terms.naer.edu.tw
Item('functional programming', 'zh-cn:函数式编程; zh-tw:函數式程式設計;'),
Item('functional programming', '函式語言程式設計=>zh-cn:函数式编程; 函式語言程式設計=>zh-tw:函數式程式設計;'),
Item('functional programming language', 'zh-cn:函数编程语言; zh-tw:函數式程式語言;'),
Item('functional programming language', '函數式程式語言=>zh-cn:函数编程语言; 函數式程式語言=>zh-sg:函数编程语言; 函數式程式語言=>zh-my:函数编程语言;'),
Item('functional programming language', '函數程式語言=>zh-cn:函数编程语言; 函數程式語言=>zh-sg:函数编程语言; 函數程式語言=>zh-my:函数编程语言;'),
Item('functional programming language', '函式程式語言=>zh-cn:函数编程语言; 函式程式語言=>zh-sg:函数编程语言; 函式程式語言=>zh-my:函数编程语言; 函式程式語言=>zh-tw:函數式程式語言;'),
Item('full high definition (full HD)', '全高清=>zh-tw:超高畫質;'),
{ type = 'text', text = [[
== G ==
]] },
-- 参考文献:刘青,温昌斌,海峡两岸科技名词差异问题分析与试解,中国科技术语,(3), 2008, 65-69
Item('garbage', '无用信息=>zh-tw:多餘的資料; 无用信息=>zh-hk:多餘的資料; 无用信息=>zh-mo:多餘的資料;'),
Item('gateway', 'zh-cn:网关; zh-tw:閘道器;'),
Item('gateway', '閘道=>zh-cn:网关; 閘道=>zh-sg:网关; 閘道=>zh-my:网关;'),
Item('Gateway, Inc.', 'zh-cn:捷威; zh-tw:桀威;'),
Item('get', 'zh-cn:获取; zh-tw:取得;'),
Item('gigabit ethernet', 'zh-cn:吉比特以太网; zh-tw:十億位元乙太網路;'),
Item('Gigabyte', '吉咖字节=>zh-hant:吉位元組; 京字节=>zh-hant:吉位元組; 吉字节=>zh-hant:吉位元組; '),
Item('Gigabyte', '吉位元組=>zh-hans:吉字节; 十億位元組=>zh-hans:吉字节; '),
Item('global', 'zh-cn:全局; zh-tw:全域;'),
Item('Global System for Mobile Communications Association', 'zh-cn:全球移动通信系统协会; zh-tw:全球行動通訊系統協會; zh-hk:全球流動通訊系統協會;'),
--Item('Google', 'zh:谷歌; zh-hant:Google; 谷歌=>zh-sg:Google; 谷歌=>zh-my:Google;'),
Item('Google Cloud Messaging', 'zh-cn:Google云消息传递; zh-tw:Google雲端通訊;'),
Item('Google Cloud Messaging', 'Google云端推送=>zh-tw:Google雲端通訊; Google云端推送=>zh-hk:Google雲端通訊; Google云端推送=>zh-mo:Google雲端通訊;'),
Item('Google Chrome Frame', 'zh-cn:谷歌浏览器内嵌框架; zh-tw:Google Chrome內嵌瀏覽框;'),
Item('Google Docs', 'zh-cn:Google文档; zh-tw:Google文件;'),
Item('Google Docs', 'zh-cn:Google 文档; zh-tw:Google 文件;'),
Item('Google Toolbar', 'zh-cn:Google工具条; zh-tw:Google工具列;'),
Item('Google Toolbar', 'zh-cn:Google 工具条; zh-tw:Google 工具列;'),
Item('Google Video', 'zh-cn:Google视频; zh-tw:Google影片;'),
Item('Google Video', 'zh-cn:Google 视频; zh-tw:Google 影片;'),
Item('graphics', 'zh-cn:图形学; zh-tw:圖學;'),
Item('graphics', '图学=>zh-cn:图形学; 图学=>zh-sg:图形学; 图学=>zh-my:图形学;'),
Item('graphics', '圖形學=>zh-tw:圖學; 圖形學=>zh-hk:圖學; 圖形學=>zh-mo:圖學;'),
Item('graphics processing unit', 'zh-cn:图形处理器; zh-tw:圖形處理器'),
Item('graphing calculator', 'zh-cn:图形计算器; zh-tw:繪圖計算機;'),
Item('greedy algorithm', 'zh-cn:贪心算法; zh-tw:貪婪演算法;'),
Item('Green Screen', 'zh-hant:綠屏; zh-cn:绿屏; zh-tw:綠白畫面; zh-hk:綠畫面;'),
Item('Green Screen of Death', 'zh-hant:綠屏死機; zh-cn:绿屏死机; zh-tw:綠白當機; zh-hk:綠畫面死機;'),
Item('greedy algorithm', '贪婪算法=>zh-cn:贪心算法; 贪婪算法=>zh-sg:贪心算法; 贪婪算法=>zh-my:贪心算法;'),
Item('greedy algorithm', '貪心算法=>zh-tw:貪婪演算法; 貪心算法=>zh-hk:貪婪演算法; 貪心算法=>zh-mo:貪婪演算法;'),
Item('greedy algorithm', '貪心演算法=>zh-tw:貪婪演算法; 貪心演算法=>zh-hk:貪婪演算法; 貪心演算法=>zh-mo:貪婪演算法;'),
Item('greedy algorithm', 'zh:貪心法; zh-cn:贪心法; zh-tw:貪婪法;'),
Item('gridlines', 'zh-cn:网格线; zh-tw:格線;'),
Item('group', 'zh-cn:组群; zh-tw:群組;'),
Item('group notice', 'zh-cn:组提示; zh-tw:群組提示;'),
Item('GSM mobile', 'zh-cn:GSM移动; zh-tw:GSM行動; zh-hk:GSM流動;'),
Item('GUI', 'zh-cn:图形用户界面; zh-tw:圖形化使用者介面;'),
Item('GUID Partition Table', 'zh-cn:全局唯一标识分区表; zh-tw:GUID磁碟分割表;'),
{ type = 'text', text = [[
== H ==
]] },
Item('hacker', 'zh-cn:黑客; zh-my:骇客; zh-tw:駭客; zh-hk:黑客;'),
Item('halfwidth', 'zh-cn:半角; zh-tw:半形;'),
Item('handler', 'zh-cn:处理函数; zh-tw:處理常式;'),
Item('handle', 'zh-cn:句柄; zh-tw:控制代碼;'),
Item('hard disk', 'zh:硬盤; zh-cn:硬盘; zh-tw:硬碟;'),
Item('hard disk drive (HDD)', 'zh-cn:硬盘驱动器; zh-tw:硬碟機;'),
Item('hard-coded', 'zh-cn:硬编码; zh-tw:寫死;'),
Item('hardware', 'zh-cn:硬件; zh-tw:硬體; zh-hk:硬件;'),
Item('hash', '哈希=>zh-tw:雜湊; 哈希=>zh-hk:雜湊; 哈希=>zh-mo:雜湊;'),
Item('hash', 'zh-cn:散列; zh-tw:雜湊;'),
Item('HDMI', 'zh-cn:高清多媒体接口; zh-tw:高畫質多媒體介面; zh-hk:高清多媒體介面;'),
Item('head crash', 'zh-cn:磁头划碰; zh-tw:磁頭損壞;'),
Item('header', 'zh-cn:标头; zh-tw:檔頭;'),
Item('header', 'zh-cn:页眉; zh-tw:頁首;'),
Item('header file', 'zh-cn:头文件; zh-tw:標頭檔;'),
Item('header file', '標頭檔案=>zh-cn:头文件; 標頭檔案=>zh-sg:头文件; 標頭檔案=>zh-my:头文件;'),
Item('header file', '表頭檔=>zh-cn:头文件; 表頭檔=>zh-sg:头文件; 表頭檔=>zh-my:头文件;'),
Item('header file', '表頭檔案=>zh-cn:头文件; 表頭檔案=>zh-sg:头文件; 表頭檔案=>zh-my:头文件;'),
Item('heapsort', 'zh-cn:堆排序; zh-tw:堆積排序;'),
Item('hearts', 'zh-cn:红心大战; zh-tw:傷心小棧;'),
Item('Help and Support', 'zh-cn:帮助与支持; zh-tw:說明與支援;'),
Item('help document', 'zh-cn:帮助文档; zh-tw:說明文件;'),
Item('Hierarchical View', 'zh-cn:分层视图; zh-tw:多層次樹狀介面;'),
Item('Hierarchical View', 'zh-cn:分层树形视图; zh-tw:多層次樹狀介面;'),
Item('hierarchy', 'zh-cn:层次结构; zh-tw:階層;'),
Item('high bandwidth memory','zh-cn:高带宽内存; zh-tw:高頻寬記憶體;'),
Item('high definition (HD)', 'zh-cn:高清; zh-tw:高畫質; zh-hk:高清;'),
Item('high definition (HD)', 'zh-cn:高清晰; zh-tw:高解析; zh-hk:高清晰;'),
Item('high fidelity (Hi-Fi)', '高保真=>zh-hk:高傳真; 高保真=>zh-mo:高傳真;'),
Item('high fidelity (Hi-Fi)', '高傳真=>zh-cn:高保真; 高傳真=>zh-sg:高保真; 高傳真=>zh-my:高保真;'),
Item('high-resolution audio', 'zh-cn:高清音频; zh-tw:高音質音訊; zh-hk:高清音頻;'),
Item('high-resolution sound quality', 'zh-cn:高清音质; zh-tw:高音質; zh-hk:高清音質;'),
Item('high-level language', 'zh-cn:高级语言; zh-tw:高階語言;'),
Item('high-level language', '高阶语言=>zh-cn:高级语言; 高阶语言=>zh-sg:高级语言; 高阶语言=>zh-my:高级语言;'),
Item('high-level language', '高级語言=>zh-tw:高階語言; 高级語言=>zh-hk:高階語言; 高级語言=>zh-mo:高階語言;'),
Item('high-level language', '高級語言=>zh-tw:高階語言; 高級語言=>zh-hk:高階語言; 高級語言=>zh-mo:高階語言;'),
Item('high-level programming language', 'zh-cn:高级编程语言; zh-tw:高階程式語言;'),
Item('high-level programming language', '高级编程語言=>zh-tw:高階程式語言; 高级编程語言=>zh-hk:高階程式語言; 高级编程語言=>zh-mo:高階程式語言;'),
Item('high-level programming language', '高级编程語言=>zh-tw:高階程式語言; 高级编程語言=>zh-hk:高階程式語言; 高级编程語言=>zh-mo:高階程式語言;'),
Item('highlight', '高亮=>zh-tw:突顯; 高亮=>zh-hk:突顯; 高亮=>zh-mo:突顯;'),
Item('highlight', '高亮显示=>zh-tw:突出顯示; 高亮显示=>zh-hk:突出顯示; 高亮显示=>zh-mo:突出顯示;'),
Item('highlight', '高亮顯示=>zh-tw:突出顯示; 高亮顯示=>zh-hk:突出顯示; 高亮顯示=>zh-mo:突出顯示;'),
Item('holographic', 'zh-cn:全息; zh-tw:全像;'),
Item('home', '住家=>zh-cn:家庭; 住家=>zh-sg:家庭; 住家=>zh-my:家庭;'),
Item('home address', '住家地址=>zh-cn:家庭地址; 住家地址=>zh-sg:家庭地址; 住家地址=>zh-my:家庭地址;'),
Item(nil, 'zh-cn:主页; zh-tw:首頁;'),
Item('hosting', 'zh:託管; zh-cn:托管; zh-tw:代管; zh-hk:寄存; zh-mo:寄存;'),
Item('hook', 'zh-cn:钩子; zh-tw:勾點;'),
Item('HyperText Markup Language', 'zh-cn:超文本标记语言; zh-tw:超文件標示語言;'),
Item('HyperText Markup Language', 'zh-cn:超文本置标语言; zh-tw:超文件標示語言;'),
{ type = 'text', text = [[
== I ==
]] },
Item('icon', 'zh:圖標; zh-cn:图标; zh-tw:圖示;'),
Item('Integrated Development Environment (IDE)', 'zh-cn:集成开发环境; zh-tw:整合式開發環境;'),
Item('Integrated Device Electronics (IDE)', 'zh-cn:集成设备电路; zh-tw:整合裝置電路;'),
Item('ID', 'zh-cn:身份; zh-tw:身分; zh-hk:身份;'),
Item('identifier', 'zh:標識符; zh-cn:标识符; zh-tw:識別碼;'),
Item('if and only if', 'zh:當且僅當; zh-cn:当且仅当; zh-tw:若且唯若;'),
-- 有可能過度轉換,編輯時須注意
Item('image', '映象=>zh-cn:镜像; 映象=>zh-sg:镜像; 映象=>zh-my:镜像;'),
Item('image file', 'zh-cn:图像文件; zh-tw:圖檔;'),
Item('image macro', 'zh-cn:表情包; zh-my:梗图; zh-tw:哏圖;'),
Item('image macro', '表情图=>zh-cn:表情包; 表情圖=>zh-cn:表情包; 表情图=>zh-tw:哏圖; 表情圖=>zh-tw:哏圖;'),
Item('imperative programming', 'zh-cn:命令式编程; zh-tw:指令式程式設計;'),
Item('implement', '實作=>zh-cn:实现; 實作=>zh-sg:实现; 實作=>zh-my:实现;'),
Item('import', 'zh-cn:导入; zh-tw:匯入;'),
Item('import', '汇入=>zh-cn:导入; 汇入=>zh-sg:导入; 汇入=>zh-my:导入;'),
Item('import', '導入=>zh-tw:匯入; 導入=>zh-hk:匯入; 導入=>zh-mo:匯入;'),
Item('Incognito mode', 'zh-cn:隐身模式; zh-my:无痕模式; zh-tw:無痕模式;'),
Item('indent', 'zh-cn:缩进; zh-tw:縮排;'),
Item('info (information)', 'zh-cn:信息; zh-my:资讯; zh-hant:資訊;'),
Item('info (information)', '资讯=>zh-sg:资讯; 資訊=>zh-sg:资讯; 资讯=>zh-cn:资讯;'),
Item('information age', 'zh-cn:信息时代; zh-hans:资讯时代; zh-tw:資訊時代; zh-hk:資訊年代;'),
Item('Information and Communication Technology', 'zh:信息与通信技术;zh-cn:信息和通信技术;zh-tw:資訊及通訊科技;'),
Item('Information Engagement', 'zh-cn:信息接触; zh-my:资讯接触; zh-tw:資訊參與;'),
Item('Information industry', 'zh-cn:信息产业; zh-tw:資訊工業;'),
Item('Information Management', 'zh-cn:信息管理; zh-hans:资讯管理; zh-tw:資訊管理;'),
Item('Information overload', 'zh-cn:信息过载; zh-hk:資訊超載; zh-tw:資訊超載;'),
Item('Information Science', 'zh:信息科學; zh-cn:信息科学; zh-my:资讯科学; zh-tw:資訊學; zh-hk:資訊科學;'),
Item('Information Science', 'zh:信息學; zh-cn:信息学; zh-my:资讯学; zh-tw:資訊學; zh-hk:資訊科學;'),
Item('information security', 'zh-cn:信息安全; zh-my:资讯安全; zh-tw:資訊安全; zh-hk:資訊保安;'),
Item('information security', '資安=>zh-cn:信息安全;'),
Item('Information Technology', 'zh:信息技術; zh-cn:信息技术; zh-sg:资讯科技; zh-my:资讯科技; zh-tw:資訊科技;'),
Item('injection', '隱碼=>zh-cn:注入; 隱碼=>zh-sg:注入; 隱碼=>zh-my:注入;'),
Item('injection', '資料隱碼=>zh-cn:注入; 資料隱碼=>zh-sg:注入; 資料隱碼=>zh-my:注入;'),
Item('inline', 'zh-cn:内联; zh-tw:行內;'),
Item('Intranet', 'zh-cn:内联网; zh-tw:內部網路;'),
Item('installation package', 'zh-cn:安装包; zh-tw:安裝套件;'),
Item('instance method', '實體方法=>zh-cn:实例方法; 實體方法=>zh-sg:实例方法; 實體方法=>zh-my:实例方法;'),
Item('integrate', 'zh-cn:集成; zh-tw:整合;'),
Item('integrated circuit', 'zh-cn:集成电路; zh-tw:積體電路; zh-hk:集成電路;'),
Item('intellectual property', 'zh-cn:知识产权; zh-tw:智慧財產權; zh-hk:知識產權;'),
Item('intellectualize', 'zh-cn:智能化; zh-tw:智慧化; zh-hk:智能化;'),
Item('intelligence', '智能型=>zh-sg:智慧型; 智能型=>zh-my:智慧型; 智能型=>zh-tw:智慧型;'),
Item('interacts', 'zh-cn:交互; zh-tw:互動;'),
Item('interactive entertainment', '互動娛樂=>zh-cn:互动娱乐; 互動娛樂=>zh-sg:互动娱乐; 互動娛樂=>zh-my:互动娱乐;'),
Item('interface', 'zh-cn:接口; zh-tw:介面;'),
Item('interface (frontstage)', '界面=>zh-tw:介面; 界面=>zh-hk:介面; 界面=>zh-mo:介面;'),
Item('internal link', '内链=>zh-tw:內部連結; 内链=>zh-hk:內部連結; 内链=>zh-mo:內部連結;'),
Item('internal link', '內鏈=>zh-tw:內部連結; 內鏈=>zh-hk:內部連結; 內鏈=>zh-mo:內部連結;'),
Item('Internet', 'zh-cn:互联网; zh-tw:網際網路; zh-hk:互聯網;'),
Item('Internet', '英特网=>zh-tw:網際網路; 英特网=>zh-hk:互聯網; 英特网=>zh-mo:互聯網;'),
Item('Internet', '因特网=>zh-tw:網際網路; 因特网=>zh-hk:互聯網; 因特网=>zh-mo:互聯網;'),
Item('Internet', '国际互联网=>zh-tw:網際網路; 国际互联网=>zh-hk:互聯網; 国际互联网=>zh-mo:互聯網;'),
Item('Internet bar', 'zh-cn:网吧; zh-tw:網咖; zh-hk:網吧;'),
Item('Internet culture', '网络文化=>zh-tw:網路文化;'),
Item('Internet forum', '網上論壇=>zh-tw:網路論壇;'),
Item('Internet forum', '網上討論區=>zh-tw:網路論壇;'),
Item('Internet Content Provider (ICP)', 'zh-cn:互联网内容提供商; zh-sg:互联网内容供应商; zh-my:互联网内容供应商; zh-tw:線上內容提供者; zh-hk:互聯網內容供應商;'),
Item('Internet Service Provider (ISP)', 'zh-cn:互联网服务提供商; zh-sg:互联网服务供应商; zh-my:互联网服务供应商; zh-tw:網際網路服務提供者; zh-hk:互聯網服務供應商;'),
Item('interpreter', 'zh-cn:解释器; zh-tw:直譯器;'),
Item('Interpreted language', 'zh-cn:解释型语言; zh-tw:直譯語言;'),
Item('Intranet', 'zh-cn:内部网络; zh-tw:內部網路; zh-hk:內聯網;'),
Item('Intranet', 'zh-cn:内部网; zh-tw:內部網路; zh-hk:內聯網;'),
Item('Internet Key Exchange', 'zh-cn:因特网密钥交换; zh-tw:網際網路金鑰交換; zh-hk:互聯網金鑰交換;'),
Item('Inter-Process Communication', 'zh-cn:进程间通信; zh-tw:行程間通訊; zh-hk:行程間通訊;'),
Item('Inter-Process', 'zh-cn:进程间; zh-tw:行程間; zh-hk:行程間;'),
-- 與call的轉換有衝突
Item('invoke', '叫用=>zh-cn:调用; 叫用=>zh-sg:调用; 叫用=>zh-my:调用;'),
{ type = 'text', text = [[
== J ==
]] },
Item('judge', 'zh-cn:评测系统; zh-tw:解題系統;'),
{ type = 'text', text = [[
== K ==
]] },
Item('kernel', '内核=>zh-tw:核心;'),
Item('kernel', '內核=>zh-tw:核心;'),
Item('key', 'zh:密鑰; zh-cn:密钥; zh-tw:金鑰;'),
Item('keyboard layout', 'zh-cn:键盘布局; zh-tw:鍵盤配置;'),
Item('keygen', 'zh-cn:注册机; zh-tw:序號產生器;'),
{ type = 'text', text = [[
== L ==
]] },
Item('landscape', 'zh-cn:横屏幕; zh-tw:橫螢幕; zh-hk:橫螢幕;'),
Item('landscape', '橫屏=>zh-tw:橫螢幕; 橫屏=>zh-hk:橫螢幕; 橫屏=>zh-mo:橫螢幕;'),
Item('Language-Oriented Programming', 'zh-cn:面向语言的程序设计; zh-tw:語言導向程式設計;'),
Item('language package', 'zh-cn:语言包; zh-tw:語言套件;'),
Item('laptop/notebook computer', 'zh-cn:笔记本电脑; zh-tw:筆記型電腦; zh-hk:手提電腦; zh-sg:手提电脑; zh-my:手提电脑;'),
Item('laptop/notebook computer', '笔记型电脑=>zh-cn:笔记本电脑; 笔记型电脑=>zh-sg:手提电脑; 笔记型电脑=>zh-my:手提电脑; 笔记型电脑=>zh-hk:手提電腦; 笔记型电脑=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '筆記本電腦=>zh-tw:筆記型電腦; 筆記本電腦=>zh-hk:手提電腦; 筆記本電腦=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '笔电=>zh-sg:手提电脑; 笔电=>zh-my:手提电脑; 笔电=>zh-hk:手提電腦; 笔电=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '筆電=>zh-sg:手提电脑; 筆電=>zh-my:手提电脑; 筆電=>zh-hk:手提電腦; 筆電=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '膝上型电脑=>zh-cn:笔记本电脑; 膝上型电脑=>zh-sg:手提电脑; 膝上型电脑=>zh-my:手提电脑; 膝上型电脑=>zh-tw:筆記型電腦;'),
Item('laptop/notebook computer', '膝上型電腦=>zh-cn:笔记本电脑; 膝上型電腦=>zh-sg:手提电脑; 膝上型電腦=>zh-my:手提电脑; 膝上型電腦=>zh-tw:筆記型電腦;'),
Item('laser', 'zh-cn:激光; zh-sg:镭射; zh-my:雷射; zh-tw:雷射; zh-hk:激光;'),
Item('LaserDisc', 'zh-cn:激光视盘; zh-sg:镭射碟; zh-my:镭射影碟; zh-tw:雷射影碟; zh-hk:鐳射影碟;'),
Item('launch bar', 'zh-cn:启动栏; zh-tw:啟動列;'),
Item('library', '函式庫=>zh-cn:库; 函式庫=>zh-sg:库; 函式庫=>zh-my:库; 函式庫=>zh-tw:函式庫; 函式庫=>zh-hk:函式庫; 函式庫=>zh-mo:函式庫'),
Item('like', 'zh-cn:点赞; zh-tw:按讚; zh-hk:讚好;'),
-- 「链接」有chaining或link的意思,而chaining和link都可被譯為「鏈結」
Item('link', 'zh-cn:链接; zh-tw:連結;'),
Item('link', '鏈結=>zh-cn:链接; 鏈結=>zh-sg:链接; 鏈結=>zh-my:链接;'),
Item('link', '连结=>zh-cn:链接; 连结=>zh-sg:链接; 连结=>zh-my:链接;'),
Item('link', '鏈接=>zh-tw:鏈結; 鏈接=>zh-hk:連結; 鏈接=>zh-mo:連結;'),
Item('linked list', 'zh-cn:链表; zh-tw:鏈結串列;'),
Item('linked list', '鏈表=>zh-tw:鏈結串列; 鏈表=>zh-hk:連結串列; 鏈表=>zh-mo:連結串列;'),
Item('livelock', 'zh-cn:活锁; zh-tw:活結;'),
Item('load', 'zh-cn:加载; zh-tw:載入;'),
Item('load', '载入=>zh-cn:加载; 载入=>zh-sg:加载; 载入=>zh-my:加载;'),
Item('load', '加載=>zh-tw:載入; 加載=>zh-hk:載入; 加載=>zh-mo:載入;'),
Item('Local Area Network', 'zh-cn:局域网; zh-tw:區域網路; zh-hk:區域網絡;'),
Item('localization', 'zh-cn:本地化; zh-tw:在地化; zh-hk:本地化;'),
Item('log', 'zh-cn:日志; zh-tw:紀錄檔;'),
Item('log in', 'zh-hans:登录; zh-hant:登入;'),
Item('log out', '登出=>zh-cn:退出; 登出=>zh-my:退出; 登出=>zh-sg:退出;'),
Item('logic device', 'zh-cn:逻辑器件; zh-tw:邏輯裝置;'),
Item('logic gate', 'zh-cn:逻辑门; zh-tw:邏輯閘; zh-hk:邏輯門;'),
Item('loop', 'zh-cn:循环; zh-tw:迴圈;'),
Item('lossless', 'zh-cn:无损; zh-tw:無失真;'),
Item('lossless compression', 'zh-cn:无损压缩; zh-tw:無失真壓縮; zh-hk:無損壓縮;'),
Item('lossy compression', 'zh-cn:有损压缩; zh-tw:失真壓縮;'),
Item('lost', 'zh-cn:丢失; zh-tw:遺失;'),
Item('low definition', 'zh-cn:低清; zh-tw:低畫質; zh-hk:低清;'),
Item('low level', 'zh-cn:低级; zh-tw:低階;'),
Item('low level', 'zh-cn:低端; zh-tw:低階;'),
Item('low-level language', 'zh-cn:低级语言; zh-tw:低階語言;'),
Item('low-level language', '低阶语言=>zh-cn:低级语言; 低阶语言=>zh-sg:低级语言; 低阶语言=>zh-my:低级语言;'),
Item('low-level language', '低级語言=>zh-tw:低階語言; 低级語言=>zh-hk:低階語言; 低级語言=>zh-mo:低階語言;'),
Item('low-level language', '低級語言=>zh-tw:低階語言; 低級語言=>zh-hk:低階語言; 低級語言=>zh-mo:低階語言;'),
Item('low-level programming language', 'zh-cn:低级编程语言; zh-tw:低階程式語言;'),
Item('low-level programming language', '低级编程語言=>zh-tw:低階程式語言; 低级编程語言=>zh-hk:低階程式語言; 低级编程語言=>zh-mo:低階程式語言;'),
{ type = 'text', text = [[
== M ==
]] },
Item('machine code', 'zh-cn:机器代码; zh-tw:機器碼; zh-hk:機械碼;'),
Item('machine code', '機器代碼=>zh-tw:機器碼; 機器代碼=>zh-hk:機械碼; 機器代碼=>zh-mo:機械碼;'),
Item('machine code', '机器码=>zh-tw:機器碼; 机器码=>zh-hk:機械碼; 机器码=>zh-mo:機械碼;'),
Item('mailing list', 'zh-cn:邮件列表; zh-tw:郵寄清單;'),
Item('mainstream media', 'zh-cn:主流媒体; zh-tw:主流媒體;'),
Item('managed code', 'zh-cn:托管代码; zh-tw:受控代碼;'),
Item('managed code', '受控代码=>zh-cn:托管代码; 受控代码=>zh-sg:托管代码; 受控代码=>zh-my:托管代码;'),
Item('managed code', '託管代碼=>zh-tw:受控代碼; 託管代碼=>zh-hk:受控代碼; 託管代碼=>zh-mo:受控代碼;'),
-- 單向轉換以避免過度轉換
Item('macro', '巨集=>zh-cn:宏; 巨集=>zh-sg:宏; 巨集=>zh-my:宏;'),
Item('macro virus', 'zh-cn:宏病毒; zh-tw:巨集病毒;'),
Item('macroblock', 'zh-cn:宏块; zh-tw:大區塊;'),
Item('macroblock', '大区块=>zh-cn:宏块; 大区块=>zh-sg:宏块; 大区块=>zh-my:宏块;'),
Item('macroblock', '宏塊=>zh-tw:大區塊; 宏塊=>zh-hk:大區塊; 宏塊=>zh-mo:大區塊;'),
Item('macroblock', '宏區塊=>zh-tw:大區塊; 宏區塊=>zh-hk:大區塊; 宏區塊=>zh-mo:大區塊;'),
Item('main memory', 'zh-hans:主存储器; zh-hant:主記憶體;'),
Item('main memory', '主存=>zh-tw:主記憶體; 主存=>zh-hk:主記憶體; 主存=>zh-mo:主記憶體;'),
Item('main memory', '内存储器=>zh-tw:主記憶體; 内存储器=>zh-hk:主記憶體; 内存储器=>zh-mo:主記憶體;'),
Item('main memory', '内存=>zh-tw:主記憶體; 内存=>zh-hk:主記憶體; 内存=>zh-mo:主記憶體;'),
Item('main memory', '內存=>zh-tw:主記憶體; 內存=>zh-hk:主記憶體; 內存=>zh-mo:主記憶體;'),
Item('mainframe', 'zh-cn:大型机; zh-tw:大型電腦;'),
Item('mapping', 'zh-cn:映射; zh-tw:對映;'),
Item('marketing', 'zh-cn:营销; zh-tw:行銷;'),
Item('Markup Language', 'zh-cn:置标语言; zh-tw:標示語言;'),
Item('Markup Language', 'zh-cn:标记语言; zh-tw:標示語言;'),
Item('Markup Language', 'zh-cn:标记语言; zh-tw:標記式語言;'),
Item('mask', '掩码=>zh-tw:遮罩; 掩码=>zh-hk:遮罩; 掩码=>zh-mo:遮罩;'),
Item('Master Boot Record', 'zh-cn:主引导记录; zh-tw:主開機紀錄;'),
-- Item('match', '匹配=>zh-tw:符合; 匹配=>zh-hk:符合; 匹配=>zh-mo:符合;'), 容易過度轉換,部分須轉換為「相符」
Item('media streamming', 'zh-cn:流媒体; zh-tw:串流媒體;'),
Item('medium', 'zh-cn:介质; zh-tw:媒介;'),
Item('medium', '媒质=>zh-tw:媒介; 媒质=>zh-hk:媒介; 媒质=>zh-mo:媒介;'),
Item('medium dependent interface', 'zh-cn:介质相关接口; zh-tw:媒體相依介面;'),
Item('megabyte', 'zh-hans:兆字节; zh-hant:百萬位元組;'),
Item('memory', 'zh-cn:存储器; zh-tw:記憶體;'),
Item('memory', '電腦記憶體=>zh-cn:存储器;'),
Item('memory card', 'zh-cn:存储卡; zh-tw:記憶卡;'),
Item('memory chip', 'zh-cn:存储芯片; zh-tw:記憶晶片;'),
Item('memory leak', 'zh-cn:内存泄漏; zh-tw:記憶體漏失;'),
Item('memory leak', 'zh-cn:内存泄漏; zh-tw:記憶體流失;'),
Item('menu', 'zh-cn:菜单; zh-tw:選單;'),
Item('merge', '归并=>zh-tw:合併; 归并=>zh-hk:合併; 归并=>zh-mo:合併;'),
Item('message', 'zh-cn:消息; zh-tw:訊息;'),
Item('message authentication code', 'zh-cn:消息认证码; zh-tw:訊息鑑別碼;'),
Item('message box', 'zh-cn:消息框; zh-tw:訊息方塊;'),
Item('message-oriented', 'zh-cn:面向消息; zh-tw:訊息導向;'),
Item('message-oriented middleware', 'zh-cn:面向消息的中间件; zh-tw:訊息導向中介層;'),
Item('meta-programming', 'zh-cn:元编程; zh-tw:元程式設計;'),
Item('meta-programming', '元編程=>zh-tw:元程式設計; 元編程=>zh-hk:元程式設計; 元編程=>zh-mo:元程式設計;'),
Item('meta-programming', 'zh-cn:超编程; zh-tw:超程式設計;'),
Item('meta-programming', '超編程=>zh-tw:超程式設計; 超編程=>zh-hk:超程式設計; 超編程=>zh-mo:超程式設計; 超編程=>zh-cn:元编程;'),
-- 台灣專業以稱元資料為主
Item('metadata', 'zh-cn:元数据; zh-tw:元資料; zh-hk:元數據;'),
-- 參考文獻:劉青,溫昌斌,海峽兩岸科技名詞差異問題分析與試解,中國科技術語,(3), 2008, 65-69
Item('metal Oxide Semiconductor', 'zh-cn:金属氧化物半导体; zh-tw:金氧半導體;'),
Item('metropolitan Area Network', 'zh-cn:城域网; zh-tw:都會網路;'),
Item('micro-blog', 'zh-cn:微博客; zh-tw:微部落格; zh-hk:微博客;'),
Item('micro-blog', 'zh-cn:微型博客; zh-tw:微型部落格; zh-hk:微型博客;'),
Item('micro-blog', '微網誌=>zh-cn:微博; 微網誌=>zh-sg:微博;'),
Item('microcontroller', 'zh-cn:单片机; zh-tw:單晶片;'),
Item('middleware', 'zh-cn:中间件; zh-tw:中介軟體;'),
Item('midrange', 'zh-cn:中级; zh-tw:中階;'),
Item('midrange', 'zh-cn:中端; zh-tw:中階;'),
Item('MIDP', 'zh-cn:移动信息设备配置文件; zh-tw:行動資訊裝置設定檔; zh-hk:流動資訊器材定義檔;'),
Item('minesweeper', 'zh-cn:扫雷; zh-tw:踩地雷;'),
Item('mixed reality', 'zh-cn:混合现实; zh-sg:混合实境; zh-my:混合实境; zh-tw:混合實境;'),
Item('mobile agent', 'zh-cn:移动代理; zh-tw:行動代理; zh-hk:流動代理;'),
Item('mobile app', 'zh-cn:移动应用; zh-tw:行動應用; zh-hk:流動應用; zh-my:流动应用;'),
Item('mobile broadcasting', 'zh-cn:移动广播; zh-tw:行動廣播; zh-hk:流動廣播; zh-my:流动广播;'),
Item('mobile browser', 'zh-cn:移动浏览器; zh-tw:行動瀏覽器; zh-hk:流動瀏覽器;'),
Item('mobile client', 'zh-cn:移动客户端; zh-tw:行動用戶端; zh-hk:流動用戶端;'),
Item('mobile code', 'zh-cn:移动代码; zh-tw:行動程式碼; zh-hk:流動程式碼;'),
Item('mobile company', 'zh-cn:移动公司; zh-tw:電信公司; zh-hk:流動公司;'),
Item('mobile commerce', 'zh-hans:移动商务; zh-hk:流動商務; zh-tw:行動商務;'),
Item('mobile communication', 'zh-cn:移动通信; zh-tw:行動通訊; zh-hk:流動通訊;'),
Item('mobile computer', 'zh-cn:移动计算机; zh-tw:行動電腦; zh-hk:流動電腦;'),
Item('mobile computing', 'zh-cn:移动计算; zh-tw:行動運算; zh-hk:流動運算;'),
Item('Mobile content management', 'zh-cn:移动内容管理; zh-tw:行動內容管理;'),
Item('mobile data', 'zh-cn:移动数据; zh-tw:行動資料; zh-hk:流動數據;'),
Item('mobile device', 'zh-cn:移动设备; zh-tw:行動裝置; zh-hk:流動裝置;'),
Item('mobile device', '移動設備=>zh-tw:行動裝置; 移動設備=>zh-hk:流動裝置; 移動設備=>zh-mo:流動裝置;'),
Item('mobile device', '移动装置=>zh-tw:行動裝置; 移动装置=>zh-hk:流動裝置; 移动装置=>zh-mo:流動裝置;'),
Item('mobile device', '移動裝置=>zh-tw:行動裝置; 移動裝置=>zh-hk:流動裝置; 移動裝置=>zh-mo:流動裝置;'),
Item('mobile device', '行動設備=>zh-tw:行動裝置; 行動設備=>zh-hk:流動裝置; 行動設備=>zh-mo:流動裝置;'),
Item('mobile device', '流動設備=>zh-tw:行動裝置; 流動設備=>zh-hk:流動裝置; 流動設備=>zh-mo:流動裝置;'),
Item('mobile Internet', 'zh-cn:移动互联网; zh-tw:行動網際網路; zh-hk:流動互聯網;'),
Item('mobile Internet Device', 'zh-cn:移动联网设备; zh-tw:行動網路裝置; zh-hk:行動聯網裝置;'),
Item('mobile network', 'zh-cn:移动网络; zh-tw:行動網路; zh-hk:流動網絡;'),
Item('mobile network operator', 'zh-cn:移动网络运营商; zh-tw:行動網路業者; zh-hk:流動網絡營辦商;'),
Item('mobile operating system', 'zh-cn:移动操作系统; zh-tw:行動作業系統; zh-hk:流動作業系統;'),
Item('mobile operator', 'zh-cn:移动运营商; zh-tw:行動業者; zh-hk:流動營辦商;'),
Item('mobile pay', 'zh-cn:移动支付; zh-tw:行動支付; zh-hk:流動支付;'),
Item('mobile phone', 'zh-cn:移动电话; zh-tw:行動電話; zh-hk:流動電話; zh-my:行动电话;'),
Item('mobile platform', 'zh-cn:移动平台; zh-tw:行動平台; zh-hk:流動平台;'),
Item('mobile product', 'zh-cn:移动产品; zh-tw:行動產品; zh-hk:流動產品;'),
Item('mobile software', 'zh-cn:移动软件; zh-tw:行動軟體; zh-hk:流動軟件;'),
Item('mobile technology', 'zh-cn:移动科技; zh-tw:行動科技; zh-hk:流動科技;'),
Item('mobile technology', 'zh-cn:移动技术; zh-tw:行動技術; zh-hk:流動技術;'),
Item('mobile telecom', 'zh-cn:移动电信; zh-tw:行動電信; zh-hk:流動電訊;'),
Item('mobile telecom operator', 'zh-cn:移动电信运营商; zh-tw:行動電信業者; zh-hk:流動電訊營辦商;'),
Item('mobile television', 'zh-cn:移动电视; zh-tw:行動電視; zh-hk:流動電視;'),
Item('mobile terminal', 'zh-cn:移动终端; zh-tw:行動終端; zh-hk:流動終端;'),
Item('mobile terminal', 'zh-cn:移动端; zh-tw:行動端; zh-hk:流動端;'),
Item('mobile version', 'zh-cn:移动版; zh-tw:行動版; zh-hk:流動版;'),
Item('mobility', 'zh-cn:移动性; zh-tw:行動性; zh-hk:流動性;'),
Item('modem', 'zh-cn:调制解调器; zh-tw:數據機;'),
Item('modem', '調變解調器=>zh-cn:调制解调器; 調變解調器=>zh-sg:调制解调器; 調變解調器=>zh-my:调制解调器;'),
Item('modifier', 'zh-cn:修饰符; zh-tw:修飾詞;'),
Item('module', 'zh-cn:模块; zh-tw:模組;'),
Item('module', '模组=>zh-cn:模块; 模组=>zh-sg:模块; 模组=>zh-my:模块;'),
Item('module', '模塊=>zh-tw:模組; 模塊=>zh-hk:模組; 模塊=>zh-mo:模組;'),
Item('monolithic kernel', 'zh-cn:宏内核; zh-tw:單核心; zh-hk:整塊性核心;'),
Item('most derived class', 'zh-cn:最底层派生类; zh-tw:最末層衍生類別;'),
Item('motherboard', 'zh-cn:主板; zh-tw:主機板;'),
Item('mouse', 'zh:鼠標; zh-cn:鼠标; zh-tw:滑鼠; zh-sg:滑鼠; zh-my:滑鼠;'),
Item('multi-channel network', 'zh-cn:多频道网络; zh-tw:多頻道聯播網;'),
Item('multi-part archive', 'zh-cn:分卷压缩; zh-tw:分割壓縮;'),
Item('multi-tasking', 'zh:多任务;zh-hant:多工;'),
Item('multiagent system', 'zh-cn:多主体系统; zh-tw:多代理系統;'),
Item('multihoming', 'zh-cn:多宿主; zh-tw:內送流量備援容錯機制;'),
Item('Multimedia Messaging Service', 'zh-cn:彩信; zh-sg:多媒体简讯; zh-my:多媒体短讯; zh-tw:多媒體簡訊; zh-hk:多媒體短訊;'),
Item('multithreading', '多緒=>zh-cn:多线程; 多緒=>zh-sg:多线程; 多緒=>zh-my:多线程;'),
Item('mutual information', 'zh-cn:互信息; zh-tw:相互資訊;'),
Item('mutual information', '交互資訊=>zh-cn:互信息; 交互資訊=>zh-sg:互信息; 交互資訊=>zh-my:互信息;'),
Item('mutual information', '交互信息=>zh-tw:相互資訊; 交互信息=>zh-hk:相互資訊; 交互信息=>zh-mo:相互資訊;'),
Item('My Document', 'zh-cn:我的文档; zh-tw:我的文件;'),
{ type = 'text', text = [[
== N ==
]] },
Item('namespace', 'zh-cn:命名空间; zh-tw:命名空間;'),
Item('namespace', '名字空间=>zh-cn:命名空间; 名字空间=>zh-sg:命名空间; 名字空间=>zh-my:命名空间; 名字空間=>zh-tw:命名空間; 名字空間=>zh-hk:命名空間; 名字空間=>zh-mo:命名空間;'),
Item('nanometer', 'zh-hans:纳米; zh-hant:納米; zh-tw:奈米'),
Item('native', '固有=>zh-tw:原生; 固有=>zh-hk:原生; 固有=>zh-mo:原生;'),
Item('narrowband', 'zh-cn:窄带; zh-tw:窄頻;'),
Item('navigation bar', 'zh-cn:导航条; zh-tw:導覽列;'),
Item('near-field communication', 'zh-hk:近場通訊; zh-hans:近场通信; zh-tw:近場通訊;'),
Item('nest', 'zh-cn:嵌套; zh-tw:巢狀;'),
Item('Net disk', 'zh:網盤; zh-cn:网盘; zh-tw:網路硬碟;'),
Item('Netbook', 'zh-cn:上网本; zh-tw:小筆電; zh-hk:NetBook;'),
Item('Netizen', '网民=>zh-tw:網友; 網民=>zh-tw:網友;'),
Item('Netscape Navigator', 'zh-cn:网景导航者; zh-tw:網景領航員;'),
Item('Network', 'zh-cn:网络; zh-tw:網路; zh-hk:網絡;'),
Item('network card', '網路卡=>zh-cn:网卡; 網路卡=>zh-sg:网卡; 網路卡=>zh-my:网卡;'),
Item('network database', 'zh-cn:网状数据库; zh-tw:網狀式資料庫; zh-hk:網絡資料庫;'),
Item('Network Neighbourhood', 'zh-cn:网上邻居; zh-tw:網路上的芳鄰;'),
Item('Network operator', 'zh-cn:网络运营商; zh-tw:網路業者; zh-hk:網絡營辦商;'),
Item('NVIDIA', 'zh-cn:英伟达; zh-tw:輝達;'),
Item('normalization', 'zh-cn:规范化; zh-tw:規格化; zh-hk:規範化;'),
Item('Norton Ghost', 'zh-cn:诺顿克隆精灵; zh-tw:諾頓魅影系統;'),
Item('null list', 'zh-cn:空列表; zh-tw:空串列;'),
Item('null string', 'zh-cn:空串; zh-tw:空字串;'),
{ type = 'text', text = [[
== O ==
]] },
Item('object', '物件=>zh-cn:对象;'),
Item('object code', 'zh-cn:目标代码; zh-tw:目的碼; zh-hk:目標碼;'),
Item('object file', '目的檔案=>zh-cn:目标文件; 目的檔案=>zh-sg:目标文件; 目的檔案=>zh-my:目标文件;'),
Item('object file', 'zh-cn:目标文件; zh-tw:目的檔; zh-hk:目標文件;'),
Item('Object-oriented', 'zh-cn:面向对象; zh-tw:物件導向;'),
Item('Object-oriented programming', 'zh-cn:面向对象编程; zh-tw:物件導向程式設計;'),
Item('octree', 'zh-cn:八叉树; zh-tw:八元樹; zh-hk:八叉樹;'),
Item('Office Shortcut Bar', 'zh-cn:快捷工具栏; zh-tw:快捷列;'),
Item('offline', '脱机=>zh-tw:離線; 脱机=>zh-hk:離線; 脱机=>zh-mo:離線;'),
Item('ones\' complement', 'zh-cn:反码; zh-tw:一補數; zh-hk:一補碼;'),
Item('ones\' complement', '二进制反码=>zh-tw:一補數; 二进制反码=>zh-hk:一補碼; 二进制反码=>zh-mo:一補碼;'),
Item('online', 'zh-cn:在线; zh-tw:線上;'),
Item('online', 'zh:联机; zh-hant:連線;'),
Item('online hard drive', 'zh-cn:网络硬盘; zh-my:网络硬碟; zh-tw:網路硬碟; zh-hk:網絡硬碟;'),
Item('online shopping', 'zh-cn:网络购物; zh-tw:網路購物; zh-hk:網絡購物;'),
Item('online shopping', '网上购物=>zh-tw:網路購物;'),
Item('online shopping', '網上購物=>zh-tw:網路購物;'),
Item('online video', 'zh-cn:在线视频; zh-tw:網路影片; zh-hk:線上影片;'),
-- Item('on the Internet', 'zh-cn:网络; zh-tw:網路; zh-hk:網上;'), 此处严重过度转换:可考虑设-{网上=>zh-tw:網路;}-的单向转换,但更建议延长词长。原理由:依台灣金融相關法律規定已連線為正式用語,非線上
Item('On-Line Transaction Processing', 'zh-cn:联机交易处理; zh-tw:線上異動處理;'),
Item('On-Line Analytical Processing', 'zh-cn:联机分析处理; zh-tw:連線分析處理;'),
Item('open', 'zh-cn:开启; zh-tw:開啟;'),
Item('Open Handset Alliance', 'zh-cn:开放手持设备联盟; zh-tw:開放手機聯盟;'),
Item('Open Mobile Alliance', 'zh-cn:开放移动联盟; zh-tw:開放行動聯盟; zh-hk:流動通訊開放制式聯盟;'),
Item('operand', 'zh-cn:操作数; zh-tw:運算元;'),
Item('operating system', 'zh-cn:操作系统; zh-tw:作業系統;'),
Item('operation object', 'zh-cn:操作对象; zh-tw:運算物件;'),
Item('operator', 'zh-cn:运算符; zh-tw:運算子;'),
Item('operator', '运算子=>zh-cn:运算符; 运算子=>zh-sg:运算符; 运算子=>zh-my:运算符;'),
Item('operator', '運算符=>zh-tw:運算子; 運算符=>zh-hk:運算子; 運算符=>zh-mo:運算子;'),
Item('operator', '操作符=>zh-tw:運算子; 操作符=>zh-hk:運算子; 操作符=>zh-mo:運算子;'),
Item('operator', '操作子=>zh-tw:運算子; 操作子=>zh-hk:運算子; 操作子=>zh-mo:運算子;'),
Item('optimal', 'zh:最优; zh-hant:最佳;'),
Item('optimization', 'zh:最優化; zh-hant:最佳化;'),
Item('optimization', 'zh-hans:优化; zh-hant:最佳化;'),
Item('Optical Network Terminals', 'zh-cn:光网络终端; zh-tw:光纖網路終端;'),
Item('outport', 'zh-cn:导出; zh-tw:匯出;'),
Item('overflow', '上限溢位=>zh-cn:溢出; 上限溢位=>zh-sg:溢出; 上限溢位=>zh-my:溢出;'),
Item('overflow', 'zh-cn:溢出; zh-tw:溢位;'),
Item('overload', 'zh-cn:重载; zh-tw:多載;'),
Item('overload', '過載=>zh-cn:重载; 過載=>zh-sg:重载; 過載=>zh-my:重载;'),
Item('override', 'zh-cn:改写; zh-tw:覆寫;'),
{ type = 'text', text = [[
== P ==
]] },
Item('package', '套件=>zh-cn:包; 套件=>zh-sg:包; 套件=>zh-my:包;'),
Item('package management system', 'zh-cn:软件包管理系统; zh-tw:軟體套件管理系統; zh-hk:軟件套件管理系統;'),
Item('package of software', 'zh-cn:软件包; zh-tw:軟體套件; zh-hk:軟件套件;'),
Item('packet switch', 'zh-cn:分组交换; zh-tw:封包交換;'),
Item('page view', 'zh:訪問量; zh-cn:访问量; zh-tw:瀏覽量;'),
Item('paint', '小畫家=>zh-cn:画图; 小畫家=>zh-sg:画图; 小畫家=>zh-my:画图;'),
Item('palette', 'zh-cn:调色板; zh-tw:調色盤;'),
Item('paradigm', 'zh-cn:范型; zh-tw:範式;'),
Item('parallel', 'zh-cn:并行; zh-tw:並列;'),
Item('parallel computing', 'zh-cn:并行计算; zh-tw:平行計算;'),
Item('parallel port', 'zh-cn:并行端口; zh-tw:並列埠;'),
Item('parallel port', '并口=>zh-tw:並列埠; 并口=>zh-hk:並列埠; 并口=>zh-mo:並列埠;'),
Item('parallel port', '并行端口=>zh-tw:並列埠; 并行端口=>zh-hk:並列埠; 并行端口=>zh-mo:並列埠;'),
Item('parallel port', '并行接口=>zh-tw:並列埠; 并行接口=>zh-hk:並列埠; 并行接口=>zh-mo:並列埠;'),
Item('parameter list', 'zh-cn:参数列表; zh-tw:參數列;'),
Item('parameter list', 'zh-cn:参数表; zh-tw:參數列;'),
Item('parent class', 'zh-cn:父类; zh-tw:父類別;'),
Item('parser', 'zh-cn:分析器; zh-tw:剖析器;'),
Item('partition', 'zh-cn:分区; zh-tw:分割區; zh-hk:分區;'),
Item('paste', 'zh-cn:粘贴; zh-tw:貼上;'),
Item('Password Authentication Protocol', 'zh-cn:密码认证协议; zh-tw:通行碼鑑別協定;'),
Item('patch', 'zh-cn:补丁; zh-tw:修補程式;'),
-- Item('pattern', 'zh-cn:模式; zh-tw:範式;'), 容易過度轉換
Item('Peer-to-Peer', 'zh-cn:点对点; zh-tw:對等;'),
Item('performance', 'zh-cn:性能; zh-tw:效能;'),
Item('permission', '許可權=>zh-cn:权限; 許可權=>zh-sg:权限; 許可權=>zh-my:权限;'),
Item('persistence', 'zh-cn:持久性; zh-tw:永續性;'),
Item('Personal Area Network', 'zh-cn:个人网; zh-tw:個人區域網路;'),
Item('personal digital assistant', 'zh-cn:个人数码助理; zh-tw:個人數位助理; zh-hk:個人數碼助理;'),
Item('personal website', 'zh-cn:个人网站; zh-tw:個人網站; zh-hk:個人網站;'),
Item('Petabyte', 'zh-hans:拍字节; zh-hant:拍位元組;'),
Item('photo', 'zh-cn:照片; zh-tw:相片;'),
Item('photocopy', 'zh-cn:复印; zh-tw:影印;'),
Item('physical layer', 'zh:物理層; zh-cn:物理层; zh-tw:實體層;'),
Item('physical address', 'zh-cn:物理地址; zh-tw:實體位址;'),
Item('physical memory', 'zh-cn:物理内存; zh-tw:實體記憶體;'),
Item('picture viewer', 'zh-cn:图片查看器; zh-tw:圖片檢視器;'),
Item('picture viewer', 'zh:图像浏览器; zh-hant:圖片檢視器;'),
Item('pipeline', 'zh-cn:流水线; zh-tw:管線; zh-hk:管線; zh-mo:管線;'),
Item('pipelining', 'zh-cn:流水线; zh-tw:管線; zh-hk:管線化; zh-mo:管線化;'),
Item('pixel', '畫素=>zh-cn:像素; 畫素=>zh-sg:像素; 畫素=>zh-my:像素; 畫素=>zh-hk:像素; 畫素=>zh-mo:像素;'),
Item('pixel', '画素=>zh-cn:像素; 画素=>zh-sg:像素; 画素=>zh-my:像素; 画素=>zh-hk:像素; 画素=>zh-mo:像素;'),
Item('placeholder', 'zh-cn:占位符; zh-tw:預留位置;'),
Item('Plug and Play', 'zh-cn:即插即用; zh-tw:隨插即用;'),
Item('plug-in', 'zh-cn:插件; zh-tw:外掛程式;'),
Item('plug-in', '外掛模組=>zh-cn:插件; 外掛模組=>zh-sg:插件; 外掛模組=>zh-my:插件;'),
Item('podcast', 'zh-cn:播客; zh-tw:播客;'),
Item('point and click', '点选=>zh-cn:点击; 点选=>zh-sg:点击; 点选=>zh-my:点击; 点选=>zh-hk:點擊; 点选=>zh-mo:點擊;'),
Item('point and click', '點選=>zh-cn:点击; 點選=>zh-sg:点击; 點選=>zh-my:点击; 點選=>zh-hk:點擊; 點選=>zh-mo:點擊;'),
Item('pointer', 'zh-cn:指针; zh-tw:指標;'),
Item('polymorphism', 'zh-cn:多态; zh-tw:多型;'),
Item('Popups', 'zh-cn:弹出窗口; zh-tw:彈出式視窗;'),
Item('port', 'zh-cn:端口; zh-tw:埠;'),
-- Item('port', '接口=>zh-tw:埠; 接口=>zh-hk:埠; 接口=>zh-mo:埠;'), 容易過度轉換
Item('port', '通訊埠=>zh-cn:端口;'),
Item('port forwarding', 'zh-cn:端口转发; zh-tw:通訊埠轉發;'),
Item('portable', 'zh-cn:便携式; zh-tw:可攜式;'),
Item('portable', '可携式=>zh-cn:便携式; 可携式=>zh-sg:便携式; 可携式=>zh-my:便携式;'),
Item('portable', '便攜式=>zh-tw:可攜式; 便攜式=>zh-hk:可攜式; 便攜式=>zh-mo:可攜式;'),
Item('portable', '便携=>zh-tw:可攜式; 便携=>zh-hk:可攜式; 便携=>zh-mo:可攜式;'),
Item('portable', '便攜=>zh-tw:可攜式; 便攜=>zh-hk:可攜式; 便攜=>zh-mo:可攜式;'),
Item('portable application', 'zh-cn:绿色软件; zh-tw:可攜式軟體; zh-hk:可攜式軟件;'),
Item('portable application', '綠色軟件=>zh-tw:可攜式軟體; 綠色軟件=>zh-hk:可攜式軟件; 綠色軟件=>zh-mo:可攜式軟件;'),
Item('portable application', '綠色軟體=>zh-tw:可攜式軟體; 綠色軟體=>zh-hk:可攜式軟件; 綠色軟體=>zh-mo:可攜式軟件;'),
Item('portable application', '便携软件=>zh-tw:可攜式軟體; 便携软件=>zh-hk:可攜式軟件; 便携软件=>zh-mo:可攜式軟件;'),
Item('portable edition', 'zh-cn:便携版; zh-tw:可攜式版本;'),
Item('portable hard drive', 'zh-cn:移动硬盘; zh-tw:行動硬碟; zh-hk:流動硬碟;'),
Item('Portable Document Format', 'zh-cn:可移植文档格式; zh-tw:可攜式文件格式;'),
Item('portal', 'zh-cn:门户系统; zh-tw:入口網站; zh-hk:入門系統;'),
Item('portal', 'zh-cn:门户网站; zh-tw:入口網站; zh-hk:入門網站;'),
Item('post', 'zh-cn:帖子; zh-sg:贴文; zh-my:贴文; zh-tw:貼文;'),
Item('power bank', 'zh-cn:移动电源; zh-tw:行動電源; zh-hk:流動充電器'),
Item('preference', '预置=>zh-tw:偏好設定; 预置=>zh-hk:參數設置; 预置=>zh-mo:參數設置;'),
Item('preference settings', 'zh-cn:首选项; zh-my:偏好设置; zh-tw:偏好設定; zh-hk:參數設置;'),
Item('prefix', 'zh-cn:前缀; zh-tw:字首;'),
Item('presentation', 'zh-cn:演示稿; zh-tw:簡報;'),
Item('print', 'zh-cn:打印; zh-tw:列印;'),
Item('print preview', 'zh-cn:打印预览; zh-tw:預覽列印;'),
Item('printer', 'zh:打印機; zh-cn:打印机; zh-tw:印表機;'),
Item('procedural generation', '程序化生成=>zh-cn:过程生成; 程序化生成=>zh-sg:过程生成; 程序化生成=>zh-my:过程生成;'),
Item('procedural programming', 'zh-cn:过程式; zh-tw:程序式;'),
Item('procedural programming', 'zh-cn:过程化; zh-tw:程序化;'),
Item('procedural programming', 'zh-cn:面向过程; zh-tw:程序導向;'),
Item('process', '連作=>zh-cn:进程; 連作=>zh-sg:进程; 連作=>zh-my:进程;'),
Item('process', '處理程序=>zh-cn:进程; 處理程序=>zh-sg:进程; 處理程序=>zh-my:进程;'),
Item('process', '进程=>zh-tw:行程; 进程=>zh-hk:行程; 进程=>zh-mo:行程;'),
-- Item('process', '行程=>zh-cn:进程; 行程=>zh-sg:进程; 行程=>zh-my:进程;'), 容易過度轉換
-- Item('process', '過程=>zh-cn:进程; 過程=>zh-sg:进程; 過程=>zh-my:进程;'), 容易過度轉換
Item('process control block', 'zh-cn:进程控制块; zh-tw:過程控制段; zh-hk:行程控制表;'),
Item('process group', 'zh-cn:进程组; zh-tw:行程群組;'),
Item('product key', 'zh-cn:产品密钥; zh-tw:產品金鑰;'),
Item('profile', 'zh-cn:配置文件; zh-tw:設定檔;'),
Item('program', 'zh-cn:程序; zh-tw:程式;'),
Item('programmer', 'zh-cn:程序编写员; zh-tw:程式設計師;'),
Item('programmer', 'zh:程序員; zh-cn:程序员; zh-tw:程式設計師;'),
Item('programmable', 'zh:可編程; zh-cn:可编程; zh-tw:可程式化;'),
Item('programmable', '可規化=>zh-cn:可编程; 可規化=>zh-sg:可编程; 可規化=>zh-my:可编程;'),
Item('programming language', 'zh-cn:编程语言; zh-tw:程式語言;'),
Item('programming language', '程式语言=>zh-cn:编程语言; 程式语言=>zh-sg:编程语言; 程式语言=>zh-my:编程语言;'),
Item('programming language', '编程語言=>zh-tw:程式語言; 编程語言=>zh-hk:程式語言; 编程語言=>zh-mo:程式語言;'),
Item('programming language', '編程语言=>zh-tw:程式語言; 編程语言=>zh-hk:程式語言; 編程语言=>zh-mo:程式語言;'),
Item('programming language', '編程語言=>zh-tw:程式語言; 編程語言=>zh-hk:程式語言; 編程語言=>zh-mo:程式語言;'),
Item('Programming paradigm', 'zh-cn:编程范型; zh-tw:程式設計範式;'),
-- Item('project', 'zh-cn:工程; zh-tw:專案;'), 容易過度轉換
Item('project', 'zh-cn:项目; zh-tw:專案;'),
Item('project', '計畫=>zh-cn:项目; 計畫=>zh-sg:项目; 計畫=>zh-my:计划; 計畫=>zh-hk:計劃; 計畫=>zh-mo:計劃;'),
Item('project page', 'zh-cn:项目页; zh-tw:計畫頁;'),
Item('protocol', 'zh:協議; zh-cn:协议; zh-tw:協定;'),
Item('prototype-based programming', 'zh-cn:基于原型的编程; zh-tw:原型程式設計;'),
Item('proximity sensor', 'zh-cn:接近传感器; zh-tw:鄰近感測器;'),
Item('Pseudocode', 'zh-cn:伪代码; zh-tw:虛擬碼; zh-hk:偽代碼;'),
Item('pattern recognition', 'zh:模式識別; zh-cn:模式识别; zh-tw:圖型識別;'),
Item('Public land mobile network', 'zh-cn:公共陆基移动网; zh-tw:公用陸上行動網路; zh-hk:公地流動網路;'),
Item('pull-down lists', 'zh-cn:下拉列表; zh-tw:下拉式清單;'),
-- 維基百科內建功能
Item('purge', '刷新缓存=>zh-tw:清除快取; 刷新缓存=>zh-hk:清除快取; 刷新缓存=>zh-mo:清除快取;'),
Item('purge', 'zh-cn:清理缓存; zh-tw:清除快取;'),
Item('push', 'zh-cn:推送; zh-tw:推播;'),
{ type = 'text', text = [[
== Q ==
]] },
Item('QR code', 'QR code=>zh-cn:QR码; QR code=>zh-sg:QR码; QR code=>zh-my:QR码; QR code=>zh-hk:QR碼; QR code=>zh-mo:QR碼;'),
Item('QR code', 'QRcode=>zh-cn:QR码; QRcode=>zh-sg:QR码; QRcode=>zh-my:QR码; QRcode=>zh-hk:QR碼; QRcode=>zh-mo:QR碼;'),
Item('QR code', '行動條碼=>zh-cn:QR码; 行動條碼=>zh-sg:QR码; 行動條碼=>zh-my:QR码; 行動條碼=>zh-hk:QR碼; 行動條碼=>zh-mo:QR碼;'),
Item('queue', 'zh-cn:队列; zh-tw:佇列;'),
Item('quadtree', 'zh-cn:四叉树; zh-tw:四元樹; zh-hk:四叉樹;'),
Item('quality', 'zh-cn:质量; zh-tw:品質; zh-hk:質素;'),
Item('quality', '品质=>zh-cn:质量; 品质=>zh-sg:质量; 品质=>zh-my:质量; 品质=>zh-hk:質素; 品质=>zh-mo:質素;'),
Item('quality', '质素=>zh-cn:质量; 质素=>zh-sg:质量; 质素=>zh-my:质量; 质素=>zh-tw:品質;'),
Item('quality', '質量=>zh-tw:品質; 質量=>zh-hk:質素; 質量=>zh-mo:質素;'),
{ type = 'text', text = [[
== R ==
]] },
Item('radio button', 'zh-cn:单选按钮; zh-tw:無線電鈕;'),
Item('radio-frequency identification', 'zh-cn:射频识别; zh-tw:無線射頻辨識; zh-hk:無線射頻辨識; zh-sg:射频识别;'),
Item('random-access memory', 'zh-cn:随机存储器; zh-tw:隨機存取記憶體'),
Item('random number', 'zh-cn:随机数; zh-tw:亂數;'),
Item('readme', 'zh-cn:自述文件; zh-tw:讀我檔案;'),
Item('read-only', 'zh-cn:只读; zh-tw:唯讀;'),
Item('read-only memory', 'zh-cn:只读存储器; zh-tw:唯讀記憶體;'),
Item('real mode', 'zh-cn:实模式; zh-tw:真實模式;'),
Item('real mode', '真实模式=>zh-cn:实模式; 真实模式=>zh-sg:实模式; 真实模式=>zh-my:实模式;'),
Item('real mode', '實模式=>zh-tw:真實模式; 實模式=>zh-hk:真實模式; 實模式=>zh-mo:真實模式;'),
Item('real-time', '实时=>zh-tw:即時; 实时=>zh-hk:即時; 实时=>zh-mo:即時;'),
Item('reboot', 'zh-cn:重启; zh-tw:重新啟動;'),
Item('reboot', '重新開機=>zh-cn:重启; 重新開機=>zh-sg:重启; 重新開機=>zh-my:重启;'),
Item('recognition', 'zh-cn:识别; zh-tw:辨識;'),
Item('recover', '回復=>zh-cn:恢复; 回復=>zh-sg:恢复; 回復=>zh-my:恢复;'),
Item('recovery disc', 'zh-cn:恢复光盘; zh-tw:還原光碟;'),
Item('recovery record', 'zh-cn:恢复记录; zh-tw:恢復記錄; zh-hk:修復記錄;'),
Item('recursion', 'zh-cn:递归; zh-tw:遞迴; zh-hk:遞歸;'),
Item('Recycle Bin', 'zh-cn:回收站; zh-tw:資源回收筒;'),
Item('Red Screen', 'zh-hant:紅屏; zh-cn:红屏; zh-tw:紅白畫面; zh-hk:紅畫面;'),
Item('Red Screen of Death', 'zh-hant:紅屏死機; zh-cn:红屏死机; zh-tw:紅白當機; zh-hk:紅畫面死機;'),
Item('Red Screen of Death', '紅屏當機=>zh-cn:红屏死机; 紅屏當機=>zh-tw:紅白當機; 紅屏當機=>zh-hk:紅畫面死機;'),
Item('redirect', 'zh-cn:重定向; zh-tw:重新導向;'),
Item('redirect page', 'zh-cn:重定向页; zh-tw:重新導向頁面;'),
Item('redirect page', '重定向頁=>zh-tw:重新導向頁面; 重定向頁=>zh-hk:重新導向頁面; 重定向頁=>zh-mo:重新導向頁面;'),
Item('redirect page', '重定向页面=>zh-tw:重新導向頁面; 重定向页面=>zh-hk:重新導向頁面; 重定向页面=>zh-mo:重新導向頁面;'),
Item('redirect page', '重定向頁面=>zh-tw:重新導向頁面; 重定向頁面=>zh-hk:重新導向頁面; 重定向頁面=>zh-mo:重新導向頁面;'),
Item('reference', 'zh-cn:引用; zh-tw:參照;'),
-- Item('reference', '參考=>zh-cn:引用; 參考=>zh-sg:引用; 參考=>zh-my:引用;'), 容易過度轉換
Item('dereference', 'zh-cn:解引用; zh-tw:解除參照;'),
Item('refresh', 'zh-cn:刷新; zh-tw:重新整理;'),
Item('refresh rate', 'zh-cn:刷新率; zh-tw:重新整理頻率;'),
Item('register', 'zh-cn:寄存器; zh-tw:暫存器;'),
Item('registry', 'zh-cn:注册表; zh-tw:登錄檔;'),
Item('regular expression', 'zh-cn:正则表达式; zh-tw:正規表示式; zh-hk:正則表達式;'),
Item('regular language', 'zh-cn:正则语言; zh-tw:正規語言; zh-hk:正則語言;'),
Item('regular language', '正规语言=>zh-cn:正则语言; 正规语言=>zh-sg:正则语言; 正规语言=>zh-my:正则语言;'),
Item('reinstallation', 'zh-cn:重装; zh-tw:重新安裝;'),
Item('relational', '關聯=>zh-cn:关系; 關聯=>zh-sg:关系; 關聯=>zh-my:关系;'),
Item('relational database', 'zh-cn:关系数据库; zh-tw:關聯式資料庫;'),
Item('release', '釋出=>zh-cn:发布; 釋出=>zh-sg:发布; 釋出=>zh-my:发布;'),
-- Item('release', 'zh-cn:发行; zh-tw:釋出;'),
Item('remote', 'zh-cn:远程; zh-tw:遠端;'),
Item('remote desktop protocol', 'zh-cn:远程桌面协议; zh-tw:遠端桌面協定;'),
Item('remote procedure call', 'zh-cn:远程过程调用; zh-tw:遠端程序呼叫;'),
-- 「可移动磁盘」對應「抽取式磁碟」(來自微軟官網)
Item('removable', 'zh-cn:可移动; zh-tw:抽取式;'),
Item('rename', 'zh-cn:重命名; zh-tw:重新命名;'),
Item('render', 'zh-cn:渲染; zh-tw:彩現;'),
Item('repeating group', 'zh-cn:重复组; zh-tw:重複群;'),
Item('reply', 'zh-hans:回复; zh-hant:回覆;'),
Item('reply', 'zh-hans:答复; zh-hant:答覆;'),
Item('Republic of Gamers', 'zh-cn:玩家国度; zh-tw:玩家共和國;'),
Item('reset', 'zh-cn:重置; zh-tw:重設;'),
Item('resolution', 'zh-cn:分辨率; zh-tw:解析度; zh-hk:解像度;'),
Item('response', '响应=>zh-tw:回應;'),
Item('Rich Internet application', 'zh-cn:丰富互联网应用程序; zh-tw:多樣化網際網路應用程式; zh-hk:多樣化互聯網應用程式;'),
Item('rollback', 'zh-cn:回滚; zh-tw:轉返;'),
Item('routine', 'zh-cn:例程; zh-tw:常式;'),
Item('run', '运行=>zh-tw:執行;运行=>zh-hk:執行;运行=>zh-mo:執行;'),
Item('running in the background', 'zh-cn:后台运行;zh-tw:背景執行;'),
{ type = 'text', text = [[
== S ==
]] },
Item('sample', 'zh-cn:示例; zh-tw:範例;'),
Item('sampling rate', 'zh-cn:采样率; zh-tw:取樣率;'),
Item('sampling rate', '取樣頻率=>zh-cn:采样率; 取樣頻率=>zh-sg:采样率; 取樣頻率=>zh-my:采样率; 取樣頻率=>zh-hk:取樣率; 取樣頻率=>zh-mo:取樣率;'),
Item('SanDisk', 'zh-cn:闪迪; zh-tw:新帝; zh-hk:SanDisk;'),
Item('SanDisk', 'zh-hans:新帝国; zh-hant:新帝國;'), -- 防止过度转换
Item('save', '保存=>zh-tw:儲存; 保存=>zh-hk:儲存; 保存=>zh-mo:儲存;'),
Item('scanner', 'zh:掃描儀; zh-cn:扫描仪; zh-tw:掃描器;'),
Item('schedule', 'zh-cn:调度; zh-tw:排程;'),
Item('scheduler', 'zh-cn:调度器; zh-tw:排程器;'),
Item('screen', 'zh-cn:屏幕; zh-tw:螢幕; zh-hk:螢幕;'),
Item('screensaver', 'zh-cn:屏幕保护程序; zh-tw:螢幕保護裝置; zh-hk:螢幕保護裝置;'),
Item('screenshot', 'zh-cn:截屏; zh-tw:螢幕擷取; zh-hk:螢幕擷取;'),
Item('script', 'zh:腳本; zh-cn:脚本; zh-tw:指令碼;'),
Item('scripting language', 'zh:腳本語言; zh-cn:脚本语言; zh-tw:手稿語言;'),
Item('scroll', 'zh-cn:滚动; zh-tw:捲動;'),
Item('scroll bar', 'zh-cn:滚动条; zh-tw:捲軸;'),
Item('scroll bar', 'zh-cn:滚动栏; zh-tw:捲軸;'),
Item('scroll box', 'zh-cn:滚动框; zh-tw:捲動方塊;'),
Item('SDK', 'zh-cn:软件开发工具包; zh-tw:軟體開發套件; zh-hk:軟件開發套件;'),
Item('search', 'zh-cn:搜索; zh-tw:搜尋;'),
Item('search box', 'zh-cn:搜索框; zh-tw:搜尋方塊;'),
Item('search key', 'zh-cn:搜索关键字; zh-tw:搜尋鍵碼;'),
Item('second normal form', 'zh-cn:第二范式; zh-tw:第二正規化;'),
Item('sector', 'zh-cn:扇区; zh-tw:磁區;'),
Item('Secure Sockets Layer', 'zh-cn:安全套接层; zh-tw:安全通訊協定;'),
Item('security software', 'zh:安全軟件; zh-cn:安全软件; zh-tw:安全軟體; zh-hk:保安軟件;'),
Item('Semantic Web', 'zh-cn:语义网; zh-tw:語意網;'),
Item('semantics', 'zh-cn:语义; zh-tw:語意;'),
Item('semaphore', 'zh:信號量; zh-cn:信号量; zh-tw:號誌; zh-hk:訊號量;'),
Item('send', 'zh:發送; zh-cn:发送; zh-tw:傳送;'),
Item('send SMS', 'zh-cn:发短信; zh-sg:发简讯; zh-my:发短讯; zh-tw:傳簡訊; zh-hk:傳短訊;'),
Item('sensor', 'zh:傳感器; zh-cn:传感器; zh-tw:感測器;'),
Item('Sequencing', 'zh-cn:测序; zh-tw:定序;'),
Item('Serial computing', 'zh-cn:串行计算; zh-tw:序列計算;'),
Item('Serial port', 'zh-hans:串行端口; zh-hant:序列埠;'),
Item('Serial port', 'zh-hans:串口;zh-hant:序列埠;'),
Item('server', 'zh:服務器; zh-cn:服务器; zh-my:伺服器; zh-tw:伺服器;'),
Item('server message block', 'zh-cn:服务器消息块; zh-tw:伺服器訊息區塊;'),
Item('server-side', 'zh-cn:服务端; zh-tw:伺服器端;'),
Item('server-side', '伺服端=>zh-cn:服务端; 伺服端=>zh-sg:服务端;'),
Item('server-side', '服務端=>zh-tw:伺服器端; 服務端=>zh-hk:伺服器端; 服務端=>zh-mo:伺服器端;'),
Item('service framework', 'zh-cn:服务框架; zh-tw:服務架構;'),
Item('session', 'zh-cn:会话; zh-tw:對談;'),
Item('Session Identity', 'zh-cn:会话标识; zh-tw:交談識別碼;'),
Item('session ID', 'zh-cn:会话标识; zh-tw:交談識別碼;'),
Item('session hijacking', 'zh-cn:会话劫持; zh-tw:連線劫持;'),
Item('setting', 'zh-cn:设置; zh-tw:設定; zh-hk:設置;'),
Item('set-top box', 'zh-cn:机顶盒; zh-tw:機上盒; zh-hk:機頂盒;'),
Item('share', 'zh-cn:共享; zh-tw:共享; zh-hk:共用;'),
Item('shared folder', '分享資料夾=>zh-cn:共享文件夹; 分享資料夾=>zh-sg:共享文件夹; 分享資料夾=>zh-my:共享文件夹; 分享資料夾=>zh-tw:共用資料夾;'),
Item('short video', 'zh-cn:短视频; zh-tw:短影音; zh-hk:短影音;'),
Item('shortcut', 'zh-cn:快捷方式; zh-tw:捷徑;'),
Item('shortcut key', 'zh-cn:快捷键; zh-tw:快速鍵;'),
Item('Single Link', 'zh-cn:单通道; zh-tw:單連結;'),
Item('signal', 'zh-cn:信号; zh-tw:訊號;'),
Item('signal', '信號=>zh-tw:訊號; 信號=>zh-hk:訊號; 信號=>zh-mo:訊號;'),
Item('signal', '讯号=>zh-cn:信号; 讯号=>zh-sg:信号; 讯号=>zh-my:信号;'),
Item('signature', 'zh-cn:签名; zh-tw:簽章;'),
Item('simulated reality', 'zh-cn:模拟现实; zh-tw:模擬實境;'),
Item('single sign-on', 'zh-cn:单点登录; zh-tw:單一登入;'),
Item('Site Identity Button', 'zh-cn:站点标识按钮; zh-tw:網站識別鈕;'),
Item('sixth normal form', 'zh-cn:第六范式; zh-tw:第六規格化;'),
Item('skin', '皮肤=>zh-tw:外觀; 皮肤=>zh-hk:佈景主題; 皮肤=>zh-mo:佈景主題;'),
Item('slider', 'zh-cn:滑块; zh-tw:滾軸;'),
Item('smart', 'zh-cn:智能; zh-sg:智慧; zh-tw:智慧型; zh-hk:智能;'),
Item('smart card', 'zh-cn:智能卡; zh-sg:智慧卡; zh-tw:智慧卡; zh-hk:智能卡;'),
Item('Smart speaker', 'zh-cn:智能音箱; zh-tw:智慧型喇叭; zh-hk:智能音箱;'),
Item('smart television', 'zh-cn:智能电视; zh-tw:智慧型電視; zh-hk:智能電視;'),
Item('smartphone', 'zh-hans:智能电话; zh-hant:智能手機; zh-cn:智能手机; zh-tw:智慧型手機; zh-hk:智能電話;'),
Item('smartwatch', 'zh-cn:智能手表; zh-tw:智慧型手錶; zh-hk:智能手錶; zh-sg:智慧手表;'),
Item('SMS', 'zh-cn:短信; zh-sg:简讯; zh-my:短讯; zh-tw:簡訊; zh-hk:短訊;'),
Item('SMS', '短消息=>zh-sg:简讯; 短消息=>zh-my:短讯; 短消息=>zh-tw:簡訊; 短消息=>zh-hk:短訊; 短消息=>zh-mo:短訊;'),
Item('SMS', '短信息=>zh-sg:简讯; 短信息=>zh-my:短讯; 短信息=>zh-tw:簡訊; 短信息=>zh-hk:短訊; 短信息=>zh-mo:短訊;'),
Item('Snowden', 'zh-cn:斯诺登; zh-tw:史諾登; zh-hk:斯諾登;'),
Item('social media', 'zh-cn:社交媒体;zh-tw:社群媒體;zh-hk:社交媒體;'),
Item('social network', 'zh-cn:社交网络; zh-tw:社群網路; zh-hk:社交網絡;'),
Item('social networking site', 'zh-cn:社交网站; zh-tw:社群網站; zh-hk:社交網站;'),
Item('socket', 'zh-cn:套接字; zh-tw:通訊端;'),
Item('socket', '通訊端點=>zh-cn:套接字; 通訊端點=>zh-my:套接字; 通訊端點=>zh-sg:套接字;'),
Item('sockets layer', 'zh-cn:套接层; zh-tw:通訊層;'),
Item('software', 'zh-cn:软件; zh-tw:軟體; zh-hk:軟件;'),
Item('software process', 'zh-cn:软件过程; zh-tw:軟體流程; zh-hk:軟件流程;'),
Item('solid archive', 'zh-cn:固实压缩; zh-tw:結實壓縮;'),
Item('Sony Mobile', 'zh-cn:索尼移动; zh-tw:索尼行動; zh-hk:索尼流動;'),
Item('Sony Mobile Communications', 'zh-cn:索尼移动通信; zh-tw:索尼行動通訊; zh-hk:索尼流動通訊;'),
Item('Sound card', 'zh-cn:声卡; zh-tw:音效卡;'),
Item('source code', 'zh-cn:源代码; zh-sg:原始码; zh-tw:原始碼;'),
Item('source code', '源代碼=>zh-sg:原始码; 源代碼=>zh-my:原始码; 源代碼=>zh-tw:原始碼; 源代碼=>zh-hk:原始碼; 源代碼=>zh-mo:原始碼;'),
Item('source code', '源码=>zh-sg:原始码; 源码=>zh-my:原始码; 源码=>zh-tw:原始碼; 源码=>zh-hk:原始碼; 源码=>zh-mo:原始碼;'),
Item('source code', '源碼=>zh-sg:原始码; 源碼=>zh-my:原始码; 源碼=>zh-tw:原始碼; 源碼=>zh-hk:原始碼; 源碼=>zh-mo:原始碼;'),
Item('source file', 'zh-cn:源文件; zh-tw:原始檔;'),
Item('spreadsheet', 'zh-cn:电子表格; zh-tw:電子試算表;'),
Item('spreadsheet', '试算表=>zh-cn:表格; 试算表=>zh-sg:表格; 试算表=>zh-my:表格;'),
Item('spreadsheet', '試算表=>zh-cn:表格; 試算表=>zh-sg:表格; 試算表=>zh-my:表格;'),
Item('SSD', 'zh-cn:固态盘; zh-tw:固態硬碟;'),
Item('statement', 'zh-cn:语句; zh-tw:語句; zh-hk:陳述式;'),
Item('stack', 'zh-cn:堆栈; zh-tw:堆疊;'),
Item('stack frame', 'zh-cn:堆栈帧; zh-tw:堆疊框; zh-hk:堆疊幀;'),
Item('stack frame', '栈帧=>zh-tw:堆疊框; 栈帧=>zh-hk:堆疊幀; 栈帧=>zh-mo:堆疊幀;'),
Item('stack-oriented', 'zh-cn:面向堆栈; zh-tw:堆疊導向;'),
Item('standard definition', 'zh-cn:标清; zh-tw:標準畫質; zh-hk:標清;'),
Item('static typing', 'zh-cn:静态类型; zh-tw:靜態型別;'),
Item('status bar', 'zh-cn:状态栏; zh-tw:狀態列;'),
Item('sticky keys', 'zh-cn:粘滞键; zh-tw:相黏鍵;'),
Item('storage', 'zh-cn:存储; zh-tw:儲存;'),
Item('storage', '存儲=>zh-tw:儲存; 存儲=>zh-hk:儲存; 存儲=>zh-mo:儲存;'),
Item('stored procedure', 'zh-cn:存储程序; zh-tw:儲存程序;'),
Item('stored procedure', '預存程序=>zh-cn:存储程序; 預存程序=>zh-sg:存储程序; 預存程序=>zh-my:存储程序;'),
Item('stored procedure', '存儲程序=>zh-tw:儲存程序; 存儲程序=>zh-hk:儲存程序; 存儲程序=>zh-mo:儲存程序;'),
Item('stored procedure', '存储过程=>zh-tw:儲存程序; 存储过程=>zh-hk:儲存程序; 存储过程=>zh-mo:儲存程序;'),
Item('stored procedure', '存儲過程=>zh-tw:儲存程序; 存儲過程=>zh-hk:儲存程序; 存儲過程=>zh-mo:儲存程序;'),
Item('stream', '串流=>zh-cn:流; 串流=>zh-sg:流; 串流=>zh-my:流;'),
Item('stream', '流式=>zh-tw:串流; 流式=>zh-hk:串流; 流式=>zh-mo:串流;'),
Item('stream cipher', 'zh-cn:流密码; zh-tw:串流加密法;'),
Item('string', 'zh-cn:字符串; zh-tw:字串;'),
Item('strong typing', 'zh-cn:强类型; zh-tw:強型別;'),
Item('submit', '送出=>zh-cn:提交; 送出=>zh-sg:提交; 送出=>zh-my:提交;'),
Item('subnet', 'zh-cn:子网; zh-tw:子網路; zh-hk:子網絡;'),
Item('subnet mask', 'zh-cn:子网掩码; zh-tw:子網路遮罩; zh-hk:子網絡遮罩;'),
Item('subroutine', 'zh-cn:子例程; zh-tw:次常式;'),
Item('suffix', 'zh-cn:后缀; zh-tw:字尾;'),
-- 有可能過度轉換,編輯時須注意
Item('support', 'zh-cn:支持; zh-tw:支援;'),
Item('Sun Microsystems', 'zh-cn:Sun微系统; zh-tw:昇陽電腦; zh-hk:太陽電腦;'),
Item('super computer', 'zh-cn:超级计算机; zh-tw:超級電腦;'),
Item('syntax highlighting', 'zh-cn:语法高亮; zh-tw:語法突顯;'),
Item('syntax highlighting', '語法凸顯=>zh-cn:语法高亮; 語法凸顯=>zh-sg:语法高亮; 語法凸顯=>zh-my:语法高亮;'),
Item('syntax highlighting', '语法高亮度=>zh-tw:語法突顯; 语法高亮度=>zh-hk:語法突顯; 语法高亮度=>zh-mo:語法突顯;'),
Item('syntax highlighting', '語法高亮度=>zh-tw:語法突顯; 語法高亮度=>zh-hk:語法突顯; 語法高亮度=>zh-mo:語法突顯;'),
Item('system (format)', '制式=>zh-tw:格式; 制式=>zh-hk:格式; 制式=>zh-mo:格式;'),
Item('System on a chip, SoC', 'zh-cn:单片系统; zh-tw:單晶片系統;'),
{ type = 'text', text = [[
== T ==
]] },
Item('tab', 'zh-cn:标签页; zh-tw:分頁;'),
Item('tab', 'zh-cn:选项卡; zh-tw:索引標籤;'),
Item('tail recursion', 'zh-cn:尾部递归; zh-tw:尾端遞迴;'),
Item('target', 'zh-cn:目标软件; zh-tw:目標軟體; zh-hk:目標軟件;'),
Item('target user', 'zh-cn:目标用户; zh-tw:目標使用者;'),
Item('task bar', 'zh-cn:任务栏; zh-tw:工作列;'),
Item('task manager', 'zh-cn:任务管理器; zh-tw:工作管理員;'),
Item('task switch', 'zh-cn:任务切换; zh-tw:工作切換;'),
Item('template', '樣板=>zh-cn:模板; 樣板=>zh-sg:模板; 樣板=>zh-my:模板; 樣板=>zh-tw:模板; 樣板=>zh-hk:模板; 樣板=>zh-mo:模板;'),
Item('Terabyte', 'zh-hans:太字节; zh-hant:兆位元組;'),
Item('terminator', 'zh-cn:终结器; zh-tw:終端子;'),
Item('ternary linked list', 'zh-cn:三叉链表; zh-tw:三元連結串列;'),
Item('ternary linked list', '三叉鏈表=>zh-tw:三元連結串列; 三叉鏈表=>zh-hk:三元連結串列; 三叉鏈表=>zh-mo:三元連結串列;'),
Item('ternary search tree', 'zh-cn:三叉搜索树; zh-tw:三元搜尋樹; zh-hk:三叉搜尋樹;'),
Item('ternary search tree', '三叉查找树=>zh-tw:三元搜尋樹; 三叉查找树=>zh-hk:三叉搜尋樹; 三叉查找树=>zh-mo:三叉搜尋樹;'),
Item('ternary tree', 'zh-cn:三叉树; zh-tw:三元樹; zh-hk:三叉樹;'),
-- Item('terrestrial', '地面=>zh-tw:無線; 地面=>zh-hk:無線; 地面=>zh-mo:無線;'), 易过度转换
Item('terrestrial television', 'zh-cn:地面电视; zh-tw:無線電視; zh-hk:地面電視;'),
Item('terrestrial broadcasting', 'zh-cn:地面广播; zh-tw:無線廣播; zh-hk:地面廣播;'),
Item('text', '文本=>zh-tw:文字; 文本=>zh-hk:文字; 文本=>zh-mo:文字;'),
Item('textbox', 'zh-cn:文本框; zh-tw:文字方塊; zh-hk:文本框;'),
Item('text editor', 'zh-cn:文本编辑器; zh-tw:文字編輯器;'),
Item('text file', 'zh-cn:文本文件; zh-tw:文字檔案;'),
Item('third normal form', 'zh-cn:第三范式; zh-tw:第三正規化;'),
Item('threads', 'zh-cn:线程; zh-tw:執行緒; zh-hk:線程;'),
Item('throw', 'zh-cn:抛出; zh-tw:丟擲; zh-hk:投擲;'),
Item('thumbnail', 'zh-cn:缩略图; zh-tw:縮圖;'),
Item('timeout', 'zh-hans:超时; zh-hant:逾時;'),
Item('title bar', 'zh-cn:标题栏; zh-tw:標題列;'),
Item('token', 'zh-cn:权标; zh-tw:符記;'),
Item('token', 'zh-cn:令牌; zh-tw:權杖;'),
Item('toolbar', 'zh-cn:工具栏; zh-tw:工具列;'),
Item('touch', 'zh-cn:触摸; zh-tw:輕觸;'),
Item('touchscreen', 'zh-cn:触摸屏; zh-tw:觸控式螢幕; zh-hk:輕觸式螢幕;'),
Item('touchscreen', 'zh-cn:触屏; zh-tw:觸控螢幕; zh-hk:輕觸螢幕;'),
Item('TouchPad', 'zh-cn:触摸板; zh-tw:觸控板;'),
Item('track', 'zh-cn:磁道; zh-tw:磁軌;'),
Item('traditional (Chinese)', '正體=>zh-cn:繁体; 正體=>zh-sg:繁体; 正體=>zh-my:繁体; 正體=>zh-hk:繁體; 正體=>zh-mo:繁體;'),
Item('Trinitron', 'zh-cn:特丽珑; zh-tw:特麗霓虹;'),
Item('troubleshooting', 'zh-cn:疑难解答; zh-tw:疑難排解;'),
Item('Turing completeness', 'zh-cn:图灵完备; zh-tw:圖靈完備;'),
Item('Turing completeness', '图灵完备=>zh-cn:图灵完备; 图灵完备=>zh-sg:图灵完备; 图灵完备=>zh-my:图灵完全;'),
Item('Turing completeness', '圖靈完全=>zh-tw:圖靈完備; 圖靈完全=>zh-hk:圖靈完備; 圖靈完全=>zh-mo:圖靈完備;'),
Item('two-dimensional code', 'zh-cn:二维码; zh-tw:二維條碼;'),
Item('two-dimensional code', '二维条码=>zh-cn:二维码; 二维条码=>zh-sg:二维码; 二维条码=>zh-my:二维码;'),
Item('two-dimensional code', '二維碼=>zh-tw:二維條碼; 二維碼=>zh-hk:二維條碼; 二維碼=>zh-mo:二維條碼;'),
Item('two\'s complement', 'zh-cn:补码; zh-tw:二補數; zh-hk:二補碼;'),
Item('two\'s complement', '二进制补码=>zh-tw:二補數; 二进制补码=>zh-hk:二補碼; 二进制补码=>zh-mo:二補碼;'),
Item('two\'s-complement integer', '补码整数=>zh-tw:二補數;'),
Item('type', '型別=>zh-cn:类型; 型別=>zh-sg:类型; 型別=>zh-my:类型;'),
Item('type', '型態=>zh-cn:类型; 型態=>zh-sg:类型; 型態=>zh-my:类型;'),
Item('type checking', 'zh-cn:类型检查; zh-tw:型別檢查;'),
Item('type system', 'zh-cn:类型系统; zh-tw:型別系統;'),
{ type = 'text', text = [[
== U ==
]] },
Item('Ultrabook', 'zh-cn:超极本; zh-tw:超極致筆電; zh-hk:Ultrabook;'),
Item('Ultrabook', '超级本=>zh-tw:超極致筆電; 超级本=>zh-hk:Ultrabook; 超级本=>zh-mo:Ultrabook;'),
Item('unary function', 'zh-cn:单参函数; zh-tw:一元函式;'),
Item('unary function', '一元函數=>zh-cn:单参函数; 一元函數=>zh-tw:一元函式;'),
Item('underflow', '欠位=>zh-cn:下溢; 欠位=>zh-my:下溢; 欠位=>zh-sg:下溢;'),
Item('underline', 'zh-cn:下划线; zh-tw:底線;'),
Item('undo', 'zh-cn:撤销; zh-tw:復原;'),
Item('undo', '撤銷=>zh-tw:復原; 撤銷=>zh-hk:復原; 撤銷=>zh-mo:復原;'),
Item('undo', '撤消=>zh-tw:復原; 撤消=>zh-hk:復原; 撤消=>zh-mo:復原;'),
-- Item('update', '升级=>zh-tw:更新; 升级=>zh-hk:更新; 升级=>zh-mo:更新;'), 容易過度轉換
-- Item('update', '升級=>zh-tw:更新; 升級=>zh-hk:更新; 升級=>zh-mo:更新;'), 容易過度轉換
Item('unified shader model', 'zh-cn:统一渲染架构; zh-tw:統一著色器架構;'),
Item('uninstall', 'zh-cn:卸载; zh-tw:解除安裝;'),
Item('uninstall', '卸載=>zh-tw:解除安裝; 卸載=>zh-hk:解除安裝; 卸載=>zh-mo:解除安裝;'),
Item('Universal Serial Bus', 'zh-cn:通用串行总线; zh-tw:通用序列匯流排;'),
Item('Universal Serial Bus', '通用串列匯流排=>zh-cn:通用序列总线; 通用串列匯流排=>zh-sg:通用串行总线; 通用串列匯流排=>zh-my:通用串行总线;'),
Item('Universal Serial Bus', '通用串行總線=>zh-tw:通用序列匯流排; 通用串行總線=>zh-hk:通用序列匯流排; 通用串行總線=>zh-mo:通用序列匯流排;'),
Item('upload', 'zh-cn:上传;zh-tw:上傳;zh-hk:上載;'),
Item('upload', '上载=>zh-tw:上傳;'),
Item('UPS', 'zh-cn:电源保护; zh-tw:不斷電系統;'),
Item('URL shortening', 'zh-cn:缩略网址; zh-tw:縮網址;'),
Item('URL shortening', '縮略網址 => zh-tw:縮網址;'),
Item('USB flash drive', 'zh-cn:U盘; zh-tw:USB隨身碟; zh-hk:USB手指;'),
Item('USB flash drive', '闪存盘=>zh-tw:隨身碟; 闪存盘=>zh-hk:USB手指; 闪存盘=>zh-mo:USB手指;'),
Item('USB flash drive', '优盘=>zh-tw:隨身碟; 优盘=>zh-hk:USB手指; 优盘=>zh-mo:USB手指;'),
Item('USB flash drive', '隨身碟=>zh-cn:U盘; 隨身碟=>zh-sg:U盘; 隨身碟=>zh-my:U盘; 隨身碟=>zh-hk:USB手指; 隨身碟=>zh-mo:USB手指;'),
Item('user', 'zh-cn:用户;zh-sg:用户;zh-my:用户;zh-hk:用戶;zh-mo:用戶;zh-tw:使用者;'),
Item('user-generated content/user-created content', 'zh-hans:用户生成内容; zh-hant:用戶生成內容; zh-tw:使用者供應內容;'),
Item('user group', '使用者群=>zh-cn:用户组;使用者群=>zh-sg:用户组;使用者群=>zh-my:用户组;使用者群=>zh-hk:用戶組;使用者群=>zh-mo:用戶組;'),
Item('user group', 'zh-tw:使用者群組;zh-cn:用户组;zh-sg:用户组;zh-my:用户组;zh-hk:用戶組;zh-mo:用戶組;'),
Item('user interface', 'zh-cn:用户界面; zh-tw:使用者介面; zh-hk:用戶介面;'),
Item('user interface', '用户介面=>zh-cn:用户界面; 用户介面=>zh-sg:用户界面; 用户介面=>zh-my:用户界面;'),
Item('user interface', 'zh-cn:人机界面; zh-tw:人機介面;'),
Item('user page', 'zh-cn:用户页; zh-tw:使用者頁面; zh-hk:用戶頁;'),
Item('user page', '用戶頁面=>zh-cn:用户页; 用戶頁面=>zh-sg:用户页; 用戶頁面=>zh-my:用户页;'),
Item('userbox', 'zh-cn:用户框; zh-tw:使用者方塊; zh-hk:用戶框;'),
Item('username', 'zh-cn:用户名; zh-tw:使用者名稱; zh-hk:用戶名;'),
Item('username', '用戶名稱=>zh-cn:用户名; 用戶名稱=>zh-sg:用户名; 用戶名稱=>zh-my:用户名;'),
{ type = 'text', text = [[
== V ==
]] },
Item('variable', 'zh-cn:变量; zh-tw:變數;'),
Item('variable', '变数=>zh-cn:变量; 变数=>zh-sg:变量; 变数=>zh-my:变量;'),
Item('variable', '變量=>zh-tw:變數; 變量=>zh-hk:變數; 變量=>zh-mo:變數;'),
Item('variable bitrate', 'zh-cn:可变码率; zh-tw:變動位元速率; zh-hk:動態編碼率;'),
Item('vector', '矢量=>zh-tw:向量; 矢量=>zh-hk:向量; 矢量=>zh-mo:向量;'),
Item('vector graphics', 'zh-cn:矢量图形; zh-tw:向量圖形;'),
Item('VGA connector', 'zh-cn:视频接口; zh-tw:視訊連接頭; zh-hk:影像端子;'),
Item('video card', 'zh-cn:显卡; zh-tw:顯示卡;'),
Item('video card', '显示卡=>zh-cn:显卡; 显示卡=>zh-sg:显卡; 显示卡=>zh-my:显卡;'),
Item('video card', '顯卡=>zh-tw:顯示卡; 顯卡=>zh-hk:顯示卡; 顯卡=>zh-mo:顯示卡;'),
Item('video conference', 'zh-cn:视频会议; zh-tw:視訊會議; zh-hk:視像會議;'),
Item('video document', 'zh-cn:视频文档; zh-tw:視訊檔案;'),
Item('video file', 'zh-cn:视频文件; zh-tw:視訊檔; zh-hk:影片檔;'),
Item('video file', 'zh-cn:视频档; zh-tw:視訊檔; zh-hk:影片檔;'),
Item('video game', 'zh-hans:视频游戏; zh-hant:電動遊戲;'),
Item('video input', 'zh-cn:视频输入; zh-tw:視訊輸入; zh-hk:視頻輸入;'),
Item('video memory', 'zh-cn:显存; zh-tw:視訊記憶體; zh-hk:影像記憶體;'),
Item('video output', 'zh-cn:视频输出; zh-tw:視訊輸出; zh-hk:影像輸出;'),
Item('video processor', 'zh-cn:视频处理器; zh-tw:影像處理器;'),
Item('video streaming', 'zh-cn:影音流; zh-tw:影音串流;'),
Item('video track', 'zh-cn:视频轨; zh-tw:視訊軌; zh-hk:視頻軌;'),
Item('videotape', 'zh-cn:录像带; zh-tw:錄影帶;'),
Item('videotape', '录相带=>zh-tw:錄影帶; 录相带=>zh-hk:錄影帶; 录相带=>zh-mo:錄影帶;'),
Item('view', 'zh-cn:查看; zh-tw:檢視;'),
Item('virtual function', 'zh-cn:虚函数; zh-tw:虛擬函式;'),
Item('virtual function', '虛擬函數=>zh-cn:虚函数; 虛擬函數=>zh-tw:虛擬函式;'),
Item('virtual machine', 'zh-cn:虚拟机; zh-tw:虛擬機器;'),
Item('virtual memory', 'zh-cn:虚拟内存; zh-tw:虛擬記憶體;'),
Item('Virtual Private Network', 'zh-cn:虚拟专用网; zh-tw:虛擬私人網路;'),
Item('virtual reality', 'zh-cn:虚拟现实; zh-sg:虚拟实境; zh-my:虚拟实境; zh-tw:虛擬實境;'),
Item('virtual reality', 'zh:虛擬現實; zh-cn:虚拟现实; zh-sg:虚拟实境; zh-my:虚拟实境; zh-tw:虛擬實境;'),
Item('visit', '造訪=>zh-cn:访问; 造訪=>zh-sg:访问; 造訪=>zh-my:访问;'),
Item('visit link', '造訪連結=>zh-cn:访问链接; 造訪連結=>zh-tw:造訪連結;'),
Item('visit link', '访问链接=>zh-cn:访问链接; 访问链接=>zh-tw:造訪連結;'),
Item('visit webpage', '造訪網頁=>zh-cn:访问网页; 造訪網頁=>zh-tw:造訪網頁;'),
Item('visit webpage', '访问网页=>zh-cn:访问网页; 访问网页=>zh-tw:造訪網頁;'),
Item('visit website', '造訪網站=>zh-cn:访问网站; 造訪網站=>zh-tw:造訪網站;'),
Item('visit website', '访问网站=>zh-cn:访问网站; 访问网站=>zh-tw:造訪網站;'),
Item('visual', 'zh-cn:可视化; zh-tw:視覺化;'),
Item('volatile (memory)', 'zh-cn:易失性; zh-tw:揮發性;'),
Item('volume', '磁碟區=>zh-cn:卷; 磁碟區=>zh-sg:卷; 磁碟區=>zh-my:卷;'),
Item('Logical volume management', 'zh-cn:逻辑卷管理; zh-tw:邏輯捲軸管理;'),
Item('von Neumann', 'zh-hant:馮諾依曼; zh-hans:冯诺伊曼; zh-tw:馮諾伊曼;zh-cn:冯诺依曼;zh-hk:馮紐曼;'),
{ type = 'text', text = [[
== W ==
]] },
Item('wallpaper', 'zh-cn:壁纸; zh-tw:桌布;'),
Item('watermark', 'zh-cn:水印; zh-tw:浮水印;'),
Item('Watson', 'zh-cn:沃森; zh-tw:華生;'),
Item('weak typing', 'zh-cn:弱类型; zh-tw:弱型別;'),
Item('web animation', 'zh-cn:网络动画; zh-tw:網路動畫; zh-hk:網絡動畫;'),
Item('webcache', 'zh-cn:网页快照; zh-tw:頁面快取檔;'),
Item('webcam', 'zh-cn:摄像头; zh-tw:網路攝影機; zh-hk:網絡攝影機;'),
Item('webcomics', 'zh-cn:网络漫画; zh-tw:網路漫畫; zh-hk:網絡漫畫;'),
Item('Wide Area Network', 'zh-cn:广域网; zh-tw:廣域網路;'),
Item('wildcard character', 'zh-cn:通配符; zh-sg:万用字元; zh-tw:萬用字元;'),
-- Item('window', 'zh-cn:窗口; zh-tw:視窗;'), Microsoft Windows操作系统稱作視窗
Item('window manager', 'zh-cn:窗口管理器; zh-tw:視窗管理員;'),
Item('Western Digital', 'zh-cn:西部数据; zh-tw:威騰電子;'),
Item('wide screen', 'zh-cn:宽屏;zh-tw:寬螢幕;zh-hk:闊螢幕;'),
Item('wide screen', '宽面屏=>zh-tw:寬螢幕;宽面屏=>zh-hk:闊螢幕;宽面屏=>zh-mo:闊螢幕;'),
Item('wide screen', '寬面屏=>zh-tw:寬螢幕;寬面屏=>zh-hk:闊螢幕;寬面屏=>zh-mo:闊螢幕;'),
Item('Windows Explorer', 'zh-cn:资源管理器; zh-tw:檔案總管;'),
Item('wizard', 'zh-cn:向导; zh-tw:精靈;'),
Item('word process', 'zh-cn:文字处理; zh-tw:文書處理;'),
Item('word processor', 'zh-cn:文字处理器; zh-tw:文書處理器;'),
Item('workgroup', 'zh-cn:工作组; zh-tw:工作群組;'),
Item('World Wide Web', 'zh-cn:万维网; zh-tw:全球資訊網; zh-hk:萬維網;'),
Item('World Wide Web Consortium', 'zh-cn:万维网联盟; zh-tw:全球資訊網協會; zh-hk:萬維網聯盟;'),
Item('write-only', 'zh-cn:只写; zh-tw:唯寫;'),
Item('write-only memory', 'zh-cn:只写存储器; zh-tw:唯寫記憶體;'),
Item('write protection', 'zh-cn:写保护; zh-tw:防寫;'),
Item('Wind River', 'zh-cn:风河; zh-tw:溫瑞爾;'),
{ type = 'text', text = [[
== X ==
]] },
Item('Xerox', 'zh-cn:施乐; zh-tw:全錄; zh-hk:施樂;'),
Item('X window system', 'zh-cn:X窗口系统; zh-tw:X視窗系統; zh-hk:X Window系統;'),
Item('X window system', 'X视窗系统=>zh-cn:X窗口系统; X视窗系统=>zh-sg:X窗口系统; X视窗系统=>zh-my:X窗口系统;'),
Item('X window system', 'X Window系统=>zh-cn:X窗口系统; X Window系统=>zh-sg:X窗口系统; X Window系统=>zh-my:X窗口系统;'),
{ type = 'text', text = [[
== Y ==
]] },
Item('Yottabyte', 'zh-hans:尧字节; zh-hant:佑位元組;'),
Item('y2k', 'zh-hans:千年虫; zh-hk:千年蟲; zh-tw:千禧蟲;'),
{ type = 'text', text = [[
== Z ==
]] },
Item('Zettabyte', 'zh-hans:泽字节; zh-hant:皆位元組;'),
Item('Zuckerberg', 'zh-cn:扎克伯格; zh-tw:祖克柏; zh-hk:朱克伯格;'),
{ type = 'text', text = [[
== 其他 ==
]] },
Item('3-D film', 'zh-hans:三维电影; zh-hant:3D電影;'),
Item('3D computer', 'zh-hans:三维计算机; zh-hant:3D電腦;'),
Item('3D computer graphics', 'zh-hans:三维计算机图形; zh-hant:3D電腦圖形;'),
Item(nil, 'zh-cn:浏览框; zh-tw:瀏覽域;'),
Item(nil, 'zh-cn:定位框; zh-tw:定位域;'),
-- Item(nil, 'zh-cn:电信; zh-tw:電信; zh-hk:電訊;'), 容易過度轉換。該詞有可能是某些電信公司官方名稱中的一部分,例如「電訊盈科」變成「電信盈科」,「中華電信」變成「中華電訊」。
Item(nil, 'zh-cn:电信商; zh-tw:電信商; zh-hk:電訊商;'),
Item(nil, 'zh-cn:电信公司; zh-tw:電信公司; zh-hk:電訊公司;'),
Item(nil, 'zh-cn:电信业; zh-tw:電信業; zh-hk:電訊業;'),
Item(nil, 'zh-cn:电信运营商; zh-tw:電信業者; zh-hk:電訊供應商;'),
Item(nil, 'zh-cn:电信服务; zh-tw:電信服務; zh-hk:電訊服務;'),
Item(nil, 'zh-cn:电信行业; zh-tw:電信行業; zh-hk:電訊行業;'),
-- 简中少用“撷”
Item(nil, '擷=>zh-cn:截; 擷=>zh-sg:截; 擷=>zh-my:截;'),
Item(nil, 'zh-cn:乔布斯; zh-tw:賈伯斯; zh-hk:喬布斯;'),
Item(nil, 'zh-cn:鲍尔默; zh-tw:巴爾默;'),
Item(nil, 'zh-cn:扒站; zh-tw:砍站;'),
{ type = 'text', text = [[
== 防止過度轉換 ==
]] },
-- 避免 字体->字型 的過度轉換
Item(nil, 'zh-hans:文字体系; zh-hant:文字體系;'),
Item(nil, 'zh-hans:汉字体系; zh-hant:漢字體系;'),
-- 避免 當機->死机 的過度轉換
Item('dead robot', 'zh-hans:当机器; zh-hant:當機器;'),
-- 避免 時脈->时钟频率 的过度转换
Item('clock rate', '時脈頻率=>zh-cn:时钟频率; 時脈頻率=>zh-sg:时钟频率; 時脈頻率=>zh-my:时钟频率;'),
Item('contacts', 'zh-hans:通讯录; zh-hant:通訊錄;'),
Item('emoji', 'zh-hans:绘文字; zh-hant:繪文字;'),
-- 避免 程式->程序 的过度转换
Item('equation', 'zh-hans:方程式; zh-hant:方程式;'),
-- 避免 資料->数据/數據 的過度轉換
Item('References', 'zh-hans:参考资料; zh-hant:參考資料;'),
Item(nil, 'zh-hans:电视频; zh-hant:電視頻;'),
Item(nil, 'zh-hans:电影片; zh-hant:電影片;'),
Item(nil, 'zh-hans:字符号; zh-hant:字符號;'),
-- 以下均为名從主人
Item('China Telecom', 'zh-hans:中国电信; zh-hant:中國電信;'),
Item('Chunghwa Telecom', 'zh-hans:中华电信; zh-hant:中華電信;'),
Item(nil, 'zh-hans:网民报告; zh-hant:網民報告;'), -- 泡泡網民報告
Item(nil, 'zh-hans:网络电视台; zh-hant:網絡電視台;'),
Item(nil, 'zh-hans:网路电视台; zh-hant:網路電視台;'),
Item(nil, 'zh-hans:网络广播电视台; zh-hant:網絡廣播電視台;'),
Item(nil, 'zh-hans:网络安全和信息化; zh-hant:網絡安全和信息化;'),
Item(nil, 'zh-hans:互联网信息办公室; zh-hant:互聯網信息辦公室;'),
Item('CAC', 'zh-hans:中共中央网络安全和信息化领导小组办公室; zh-hant:中共中央網絡安全和信息化領導小組辦公室;'),
Item('CNCERT', 'zh-hans:国家互联网应急中心; zh-hant:國家互聯網應急中心;'),
Item('CNCERT', 'zh-hans:互联网应急中心; zh-hant:互聯網應急中心;'),
Item('CNNIC', 'zh-hans:中国互联网络信息中心; zh-hant:中國互聯網絡信息中心;'),
Item('CNNIC', 'zh-hans:互联网络信息中心; zh-hant:互聯網絡信息中心;'),
Item('Industry and Information Technology', 'zh-hans:工业和信息化; zh-hant:工業和信息化;'), -- 中华人民共和国工业和信息化部
Item('National Administration of Surveying, Mapping and Geoinformation', 'zh-hans:国家测绘地理信息局; zh-hant:國家測繪地理信息局;'),
Item('Hudong Baike', 'zh-hans:互动百科; zh-hant:互動百科;'),
Item('World Internet Conference', 'zh-hans:世界互联网大会; zh-hant:世界互聯網大會;'),
Item('Alibaba Cloud', 'zh-hans:阿里云计算; zh-hant:阿里雲計算;'),
Item('Tencent Cloud', 'zh-hans:腾讯云计算; zh-hant:騰訊雲計算;'),
Item('Baidu Cloud', 'zh-hans:百度云计算; zh-hant:百度雲計算;'),
Item('Baidu Cloud', 'zh-hans:百度网盘; zh-hant:百度網盤;'),
Item('LeCloud', 'zh-hans:乐视云计算; zh-hant:樂視雲計算;'),
Item('ByteDance', 'zh-hans:字节跳动; zh-hant:字節跳動;'),
Item(nil, 'zh-hans:人渣文本; zh-hant:人渣文本;'),
Item(nil, 'zh-hans:资讯台; zh-hant:資訊台;'),
Item(nil, 'zh-hans:资讯频道; zh-hant:資訊頻道;'), -- 避免电视频道名称过度转换
-- 防止「共享」過度轉換
Item('Wikimedia Commons', 'zh-hans:维基共享资源; zh-hant:維基共享資源;'),
Item('shareware', 'zh-cn:共享软件; zh-tw:共享軟體;'),
-- 防止「數據」過度轉換
Item('Wikidata', 'zh-hans:维基数据; zh-hant:維基數據;'),
-- 以下均为防止“视频”过度转换
Item('Baidu Video', 'zh-hans:百度视频; zh-hant:百度視頻;'),
Item('Netease Video', 'zh-hans:网易视频; zh-hant:網易視頻;'),
Item('Sina Video', 'zh-hans:新浪视频; zh-hant:新浪視頻;'),
Item('Sohu Video', 'zh-hans:搜狐视频; zh-hant:搜狐視頻;'),
Item('Tencent Video', 'zh-hans:腾讯视频; zh-hant:騰訊視頻;'),
Item('Tik Tok', 'zh-hans:抖音短视频; zh-hant:抖音短視頻;'),
Item('Tudou Video', 'zh-hans:土豆视频; zh-hant:土豆視頻;'),
Item('Vigo Video', 'zh-hans:火山小视频; zh-hant:火山小視頻;'),
Item('Xigua Video', 'zh-hans:西瓜视频; zh-hant:西瓜視頻;'),
Item('Youku Video', 'zh-hans:优酷视频; zh-hant:優酷視頻;'),
-- 以下均为防止“博客”过度转换
Item('Netease Blog', 'zh-hans:网易博客; zh-hant:網易博客;'),
Item('Sina Blog', 'zh-hans:新浪博客; zh-hant:新浪博客;'),
Item('Sohu Blog', 'zh-hans:搜狐博客; zh-hant:搜狐博客;'),
Item('Tencent Blog', 'zh-hans:腾讯博客; zh-hant:騰訊博客;'),
Item('Williamlong', 'zh-hans:月光博客; zh-hant:月光博客;'),
Item('bookstw', 'zh-hans:博客来; zh-hant:博客來;'), -- 台灣的博客來網路書店
-- 以下均为防止“相册”过度转换
Item('Netease Album', 'zh-hans:网易相册; zh-hant:網易相冊;'),
Item('Baidu Album', 'zh-hans:百度相册; zh-hant:百度相冊;'),
-- 以下均为防止“搜索”过度转换
Item('360 Search', 'zh-hans:360搜索; zh-hant:360搜索;'),
Item('Baidu Search', 'zh-hans:百度搜索; zh-hant:百度搜索;'),
Item('Sogou Search', 'zh-hans:搜狗搜索; zh-hant:搜狗搜索;'),
Item(nil, 'zh-hans:360综合搜索; zh-hant:360綜合搜索;'),
-- 防止公司名稱過度轉換
Item('Alibaba.com Ltd.', 'zh-hans:阿里巴巴网络; zh-hant:阿里巴巴網絡;'),
Item('Alibaba.com Ltd.', 'zh-hans:谷翔信息技术; zh-hant:谷翔信息技術;'),
Item('Sumavision', 'zh-hans:数码视讯; zh-hant:數碼視訊;'), -- 中国大陆的一家CA供应商
Item('Smartone', 'zh-hans:数码通; zh-hant:數碼通;'), -- 香港通信公司
Item('MODA', 'zh-hant:數位發展部; zh-hans:数位发展部;'), -- [[中華民國數位發展部]]
Item('MODA', 'zh-hant:數位部; zh-hans:数位部;'),
-- 避免 社区->社群 的過度轉換
Item(nil, 'zh-hans:草榴社区; zh-hant:草榴社區;'),
-- 避免 移动版->行動版/流動版 的過度轉換
Item(nil, 'zh-hans:移动版面; zh-hant:移動版面;'),
Item(nil, 'zh-hans:移动版块; zh-hant:移動版塊;'),
-- 避免 智能->智慧/智慧型 的過度轉換
Item(nil, 'zh-hans:智能ABC; zh-hant:智能ABC;'),
Item(nil, 'zh-hans:智慧城市; zh-hant:智慧城市;'),
-- 避免 命令列->命令行 的過度轉換
Item(nil, 'zh-hans:命令列表; zh-hant:命令列表;'),
-- 避免 支持->支援 的過度轉換
Item('support vector', 'zh-hans:支持向量; zh-hant:支持向量;'),
Item('supporter', 'zh-hans:支持者; zh-hant:支持者;'),
Item('I support', 'zh-hans:我支持; zh-hant:我支持;'),
Item('support me', 'zh-hans:支持我; zh-hant:支持我;'),
Item('support he', 'zh-hans:他支持; zh-hant:他支持;'),
Item('support he', 'zh-hans:支持他; zh-hant:支持他;'),
Item('support she', 'zh-hans:她支持; zh-hant:她支持;'),
Item('support she', 'zh-hans:支持她; zh-hant:支持她;'),
-- 避免 最优->最佳 的過度轉換
Item(nil, 'zh-hans:最优秀; zh-hant:最優秀;'),
Item(nil, 'zh-hans:最优美; zh-hant:最優美;'),
Item(nil, 'zh-hans:最优质; zh-hant:最優質;'),
Item(nil, 'zh-hans:最优先; zh-hant:最優先;'),
-- 避免 导出->匯出 的過度轉換
Item(nil, 'zh-hans:推导; zh-hant:推導;'),
-- 避免 子类->子類別 的過度轉換
Item(nil, '子类别=>zh-tw:子類別; 子类别=>zh-hk:子類別; 子类别=>zh-mo:子類別;'),
Item(nil, 'zh-hans:子类型; zh-hant:子類型;'),
-- 避免 C++类->C++類別 的過度轉換
Item(nil, 'zh-hans:C++类似; zh-hant:C++類似;'),
Item(nil, 'zh-hans:C++类型; zh-hant:C++類型;'),
-- 避免 C++的类->C++的類別 的過度轉換
Item(nil, 'zh-hans:C++的类型; zh-hant:C++的類型;'),
-- 避免 Java类->Java類別 的過度轉換
Item(nil, 'zh-hans:Java类似; zh-hant:Java類似;'),
Item(nil, 'zh-hans:Java类型; zh-hant:Java類型;'),
-- 避免 Java的类->Java的類別 的過度轉換
Item(nil, 'zh-hans:Java的类型; zh-hant:Java的類型;'),
-- 避免 复杂度类->複雜度類別 的過度轉換
Item(nil, 'zh-hans:复杂度类似; zh-hant:複雜度類似;'),
-- 避免 基于类->類別基礎 的過度轉換
Item(nil, 'zh-hans:基于类似; zh-hant:基於類似;'),
Item(nil, 'zh-hans:基于类型; zh-hant:基於類型;'),
-- 避免 布尔->布林 的過度轉換
Item(nil, 'zh-hans:·布尔; zh-hant:·布爾;'),
-- 避免 圖學->图形学 的過度轉換
Item(nil, 'zh-hans:地图学; zh-hant:地圖學;'),
Item(nil, 'zh-hans:试图学; zh-hant:試圖學;'),
Item(nil, 'zh-hans:企图学; zh-hant:企圖學;'),
Item(nil, 'zh-hans:电图学; zh-hant:電圖學;'),
-- 避免 執行->运行 的過度轉換
Item('executable', 'zh-hans:可执行; zh-hant:可執行;'),
Item('executor', 'zh-hans:执行者; zh-hant:執行者;'),
-- 避免 高亮->突顯 的過度轉換
Item(nil, 'zh-hans:高亮度; zh-hant:高亮度;'),
-- 避免 访问->存取 的過度轉換
Item(nil, 'zh-hans:访问学者; zh-hant:訪問學者;'),
-- 避免 存取->访问 的過度轉換
Item('random-access', 'zh-hans:随机存取; zh-hant:隨機存取;'),
-- 避免 代码/代碼->程式碼 的過度轉換
Item(nil, '程序代码=>zh-tw:程式碼; 程序代码=>zh-hk:程式碼; 程序代码=>zh-mo:程式碼;'),
Item(nil, '程序代碼=>zh-tw:程式碼; 程序代碼=>zh-hk:程式碼; 程序代碼=>zh-mo:程式碼;'),
Item(nil, '程式代码=>zh-tw:程式碼; 程式代码=>zh-hk:程式碼; 程式代码=>zh-mo:程式碼;'),
Item(nil, '程式代碼=>zh-tw:程式碼; 程式代碼=>zh-hk:程式碼; 程式代碼=>zh-mo:程式碼;'),
Item(nil, 'zh-hans:类型代码; zh-hant:類型代碼;'),
-- 避免 码率/碼率->位元速率 的過度轉換
Item(nil, 'zh-hans:误码率; zh-hant:誤碼率;'),
Item('rate of coincident code', 'zh-hans:重码率;zh-hant:重碼率;'),
-- 避免 交互->互動 的過度轉換
Item(nil, '交互資訊=>zh-tw:交互資訊; 交互資訊=>zh-hk:交互資訊; 交互資訊=>zh-mo:交互資訊;'),
-- 避免 程序->程式 的過度轉換
Item(nil, '預存程序=>zh-tw:預存程序; 預存程序=>zh-hk:預存程序; 預存程序=>zh-mo:預存程序;'),
-- 避免 復原->撤销 的過度轉換
Item(nil, 'zh-hans:回复原; zh-hant:回復原;'),
Item(nil, 'zh-hans:恢复原; zh-hant:恢復原;'),
-- 避免 模拟/模擬->類比 的過度轉換
Item('analogizer', 'zh-hans:模拟器; zh-hant:模擬器;'),
-- 避免 檔案->文件 的過度轉換
Item('archives', 'zh-hans:档案馆; zh-hant:檔案館;'),
Item('archives', 'zh-hans:档案室; zh-hant:檔案室;'),
-- 避免 字符->字元 的過度轉換
Item('Hong Kong Supplementary Character Set', 'zh-hans:香港增补字符集; zh-hant:香港增補字符集;'),
Item('Macao Supplementary Character Set', 'zh-hans:澳门增补字符集; zh-hant:澳門增補字符集;'),
-- 避免 資訊->信息 的過度轉換
Item('Macao Information System Character Set', 'zh-hans:澳门资讯系统字集; zh-hant:澳門資訊系統字集;'),
-- 避免 数据包->封包 的過度轉換
Item(nil, 'zh-cn:数据包括; zh-tw:資料包括; zh-hk:數據包括;'),
Item(nil, 'zh-cn:数据包含; zh-tw:資料包含; zh-hk:數據包含;'),
-- 避免 比特->位元 的過度轉換
Item('bitcent', 'zh-hans:比特分; zh-hant:比特分;'),
Item('bitcoin', 'zh-hans:比特币; zh-hant:比特幣;'),
Item('BitComet', 'zh-hans:比特彗星; zh-hant:比特彗星;'),
Item('BitSpirit', 'zh-hans:比特精灵; zh-hant:比特精靈;'),
Item('micro-bitcoin', 'zh-hans:微比特; zh-hant:微比特;'),
Item('milli-bitcoin', 'zh-hans:毫比特; zh-hant:毫比特;'),
Item('function library', 'zh-cn:函数库; zh-tw:函式庫;'),
Item('functional', 'zh-hans:函数式; zh-hant:函數式;'), -- 避免 函数/函數->函式 的過度轉換
Item('Office Suite', 'zh-hans:办公室套件; zh-hant:辦公室套件;'), -- 避免 套件->包 的過度轉換
Item('PPTV', 'zh-hans:PP视频; zh-hant:PP視頻;'), -- 避免 PP视频->PP影片 的過度轉換
Item('real mode', '真实模式=>zh-tw:真實模式; 真实模式=>zh-hk:真實模式; 真实模式=>zh-mo:真實模式;'), -- 避免 实模式->真實模式 的過度轉換
Item('rolling update', 'zh-hans:滚动更新; zh-hant:滾動更新;'), -- 避免 滚动->捲動 的過度轉換
Item('script kiddie', 'zh-hans:脚本小子; zh-hant:腳本小子;'), -- 避免 脚本->指令碼 的過度轉換
Item('tablet computer', 'zh-hans:平板电脑; zh-hant:平板電腦;'), -- 避免 电脑/電腦->计算机 的過度轉換
-- 避免 佈景->布景 的過度轉換
Item('theme', '布景主题=>zh-tw:佈景主題; 佈景主題=>zh-tw:佈景主題;'),
-- 避免 字型->字体 的過度轉換
Item('wubi', 'zh-hans:五笔字型; zh-hant:五筆字型;'),
-- 避免 运算符->運算子 的過度轉換
Item('operator', 'zh-hans:运算符号; zh-hant:運算符號;'),
-- 避免 代码/代碼->程式碼 的過度轉換
Item('code list', 'zh-hans:代码表; zh-hant:代碼表;'),
-- 避免 国家安全局->國家安全域 的過度轉換
Item('NSB', '国家安全局=>zh-tw:國家安全局; 國家安全局=>zh-tw:國家安全局;'),
-- 避免 完全屏蔽->完全螢幕蔽 的過度轉換
Item('block', 'zh-hans:完全屏蔽; zh-hant:完全屏蔽;'),
-- 避免 中文介面->中文接口 的過度轉換
Item('XXX language interface', 'zh-cn:文界面; zh-tw:文介面; zh-hk:文介面;'),
Item('China Computer Federation', 'zh-hans:中国计算机学会; zh-hant:中國計算機學會;'),
},
}
a604cd2a89f68174ec9a0f5c9462fc1099f12bef
Template:Infobox Douyin personality
10
211
440
2024-07-24T10:42:18Z
zhwp>Manchiu
0
回退[[Special:Contributions/116.10.81.244|116.10.81.244]]([[User talk:116.10.81.244|对话]])的编辑,改回[[Special:Contributions/Patlabor Ingram|Patlabor Ingram]]的最后一个版本
wikitext
text/x-wiki
{{Infobox
| child = {{Yesno|{{{embed|no}}}}}
| bodyclass = biography vcard
| title = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes|<div align=center style="background-color:#411445; color:#FFF;">'''抖-{}-音资料'''</div>}}
| abovestyle = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||background-color: #411445; color: white}}
| above = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{br separated entries
|1={{#if:{{{honorific prefix|{{{honorific_prefix|}}}}}}|<span class="honorific-prefix" style="font-size: small">{{{honorific prefix|{{{honorific_prefix|}}}}}}</span>}}
|2={{#if:{{{name|<includeonly>{{PAGENAMEBASE}}</includeonly>}}}|<span class="fn">{{{name|{{PAGENAMEBASE}}}}}</span>}}
|3={{#if:{{{honorific suffix|{{{honorific_suffix|}}}}}}|<span class="honorific-suffix" style="font-size: small">{{{honorific suffix|{{{honorific_suffix|}}}}}}</span>}}
}}
}}
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{logo|}}}|size={{{logo_size|}}}|sizedefault=250px|alt={{{logo_alt|}}}}}
| caption = {{{logo caption|}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{image|}}}|size={{{image size|{{{image_size|{{{imagesize|}}}}}}}}}|sizedefault=frameless|upright=1|alt={{{alt|}}}|suppressplaceholder=yes}}
| caption2 = {{{image caption|{{{caption|{{{image_caption|}}}}}}}}}
| headerstyle = background-color: {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes|{{{header-color|transparent}}}|#411445; color: white}}; line-height: 1.5em
| labelstyle = white-space: nowrap;
| header1 = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{#if:{{{birth_name|}}}{{{birth_date|}}}{{{birth_place|}}}{{{death_date|}}}{{{death_place|}}}{{{height|}}}{{{nationality|}}}{{{residence|}}}{{{occupation|}}}|个人资料}}}}
| label3 = 出生
| data3 = {{br separated entries|1={{#if:{{{birth_name|}}}|<span style="white-space:normal;">{{{birth_name|}}}</span>}}|2={{{birth_date|}}}|3={{#if:{{{birth_place|}}}|<span class="birthplace">{{{birth_place|}}}</span>}}}}
| label4 = 逝世
| data4 = {{br separated entries|1={{{death_date|}}}|2={{#if:{{{death_place|}}}|<span class="deathplace">{{{death_place|}}}</span>}}}}
| label5 = 出道地點
| data5 = {{{Origin|{{{origin|}}}}}}
| label6 = 國籍
| data6 = {{{nationality|}}}
| class6 = category
| label7 = 教育程度
| data7 = {{{education|}}}
| label8 = 居住地
| data8 = {{{residence|}}}
| class8 = {{#if:{{{death_date|}}}{{{death_place|}}}||label}}
| label9 = 職業
| data9 = {{{occupation|}}}
| class9 = role
| label10 = 身高
| data10 = {{#if:{{{height_m|{{{height_cm|}}}}}}{{{height_ft|}}}{{{height_in|}}} | {{convinfobox|{{{height_m|{{{height_cm|}}}}}}|{{#if:{{{height_m|}}}|m|cm}}|{{{height_ft|}}}|ft|{{{height_in|}}}|in}} }}{{#if:{{{height|}}} | {{Infobox person/height|{{{height|}}}}} }}
| label11 = 宗教信仰
| data11 = {{{religion|}}}
| class11 = category
| label12 = 伴侶
| data12 = {{{partner|}}}
| label13 = 配偶
| data13 = {{{spouse|}}}
| label14 = 簽名
| data14 = {{#if:{{{signature|}}}|{{#invoke:InfoboxImage|InfoboxImage|image={{{signature|}}}|size={{{signature_size|}}}|sizedefault=150px|alt={{{signature alt|{{{signature_alt|}}}}}}}} }}
| label15 = 網站
| data15 = {{{website|{{{homepage|{{{URL|}}}}}}}}}
| header20 = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{#if:{{{pseudonym|}}}{{{channel_name|}}}{{{channel_url|}}}{{{channel_direct_url|}}}{{{years active|{{{years_active|{{{yearsactive|}}}}}}}}}{{{genre|}}}{{{subscribers|}}}{{{views|}}}{{{network|}}}{{{associated_acts|}}}{{{catchphrase(s)|}}}|抖音-{}-资料}}}}
| label21 = 網名
| data21 = {{{pseudonym|}}}
| label22 = 頻道
| data22 = {{#if:{{{channel_url|}}}|[{{{channel_url|}}} {{#if:{{{channel_display_name|}}}|{{{channel_display_name|}}}|{{{channels|}}}}}]}}
| label23 = 頻道
| data23 = {{{channels|}}}
| label24 = 頻道
| data24 = {{{channels|}}}
| label25 = 頻道
| data25 = {{{channels|}}}
| label26 = 創辦人
| data26 = {{{creator|}}}
| label27 = 活躍年代
| data27 = {{{years active|{{{years_active|{{{yearsactive|}}}}}}}}}
| label28 = 類型
| data28 = {{{genre|}}}
| label29 = 粉丝数
| data29 = {{br separated entries|1={{{subscribers|}}}|2={{#if:{{{subscriber_date|}}}|(截至{{{subscriber_date|}}})|}}}}
| label30 = 總-{zh-cn:播放数;zh-hk:點擊率;zh-tw:點閱數;}-
| data30 = {{br separated entries|1={{{views|}}}|2={{#if:{{{view_date|}}}|(截至{{{view_date|}}})|}}}}
| label31 = [[多频道网络|網-{zh-cn:络;zh-hk:絡;zh-tw:路;}-]]
| data31 = {{{network|}}}
| label32 = 点赞量
| data32 = {{br separated entries|1={{{Praise quantity|}}}|2={{#if:{{{Praise quantity_date|}}}|(截至{{{Praise quantity_date|}}})|}}}}
| label33 = 相關團體
| data33 = {{{associated_acts|}}}
| label34 = 口頭禪
| data34 = {{{catchphrase(s)|}}}
| belowstyle = color: darkslategray;
| below = {{#if:{{{stats_update|}}}|更新于{{{stats_update}}}|}} {{#if:{{{extra_information|}}}|{{{extra_information}}}}}
}}{{#ifeq:{{{nocat|false}}}|false|}}<noinclude>{{documentation}}</noinclude>
ee4ae4e61a837fd290b590698a43e2e81138239e
Module:Transclusion count/data/A
828
119
232
2024-07-28T19:51:27Z
zhwp>A2093064-bot
0
[[User:A2093064-bot/task/44|機器人44]]:更新模板使用量
Scribunto
text/plain
return {
["ACG專題"] = 17000,
["ACG專題/class"] = 22000,
["ACG專題/importance"] = 22000,
["AIGA_arrow"] = 5900,
["ARG"] = 3200,
["AUS"] = 7100,
["AUT"] = 2900,
["Abbr"] = 760000,
["About"] = 16000,
["Add_new_taxon"] = 57000,
["Adjacent_stations"] = 18000,
["Adjacent_stations/styles.css"] = 18000,
["AfdLinkNext"] = 9200,
["Age"] = 118000,
["Age_in_years"] = 2100,
["Age_in_years_and_days"] = 2200,
["Albumcover"] = 7200,
["Align"] = 56000,
["AllMovie_title"] = 5300,
["Ambox"] = 223000,
["Ambox/style.css"] = 224000,
["Amg_movie"] = 3600,
["Anchor"] = 6100,
["Antarctica-geo-stub"] = 5200,
["Archive_box"] = 3000,
["Archives"] = 3500,
["Arrow"] = 5900,
["Article"] = 48000,
["ArticleHistory"] = 5500,
["Article_history"] = 8200,
["Articles_by_Importance"] = 3500,
["Articles_by_Quality"] = 6400,
["Articles_by_Quality/down"] = 6400,
["Articles_by_Quality/total"] = 6400,
["Articles_by_Quality/up"] = 6400,
["As_of"] = 2900,
["Asbox"] = 404000,
["Asteroid-stub"] = 6800,
["Audio"] = 9600,
["Austria-geo-stub"] = 2300,
["Authority_control"] = 233000,
["AutoLink"] = 5100,
["Auto_link"] = 2900,
["Autolink"] = 2200,
["Automatic_Taxobox"] = 6500,
["Automatic_taxobox"] = 33000,
["Module:About"] = 16000,
["Module:Adjacent_stations"] = 41000,
["Module:Adjacent_stations/i18n"] = 41000,
["Module:Adjacent_stations/港鐵"] = 2700,
["Module:Age"] = 123000,
["Module:Anchor"] = 6100,
["Module:Arguments"] = 3990000,
["Module:Article_history"] = 8200,
["Module:Article_history/Category"] = 8200,
["Module:Article_history/config"] = 8200,
["Module:Asbox"] = 404000,
["Module:Asbox_stubtree"] = 2500,
["Module:Authority_control"] = 233000,
["Module:Authority_control/auxiliary"] = 59000,
["Module:Authority_control/config"] = 233000,
["Module:Automated_taxobox"] = 33000,
["Module:Autotaxobox"] = 180000,
}
3a63c5444da3214c092266b9bbf97f9a8424e3cc
Module:Transclusion count/data/B
828
242
503
2024-07-28T19:51:37Z
zhwp>A2093064-bot
0
[[User:A2093064-bot/task/44|機器人44]]:更新模板使用量
Scribunto
text/plain
return {
["BD"] = 17000,
["BD/isYear"] = 299000,
["BEL"] = 4300,
["BHKG"] = 2800,
["BLP"] = 30000,
["BLP_unsourced"] = 4900,
["BLPsources"] = 6200,
["BRA"] = 4100,
["BS-map"] = 2100,
["BS-map/map"] = 2100,
["Babel"] = 5000,
["Baseballstats"] = 2300,
["Based_on"] = 3800,
["Basepage_subpage"] = 115000,
["Bd"] = 299000,
["Bio_icon"] = 2500,
["Bio_icon2"] = 2500,
["Birth_date"] = 29000,
["Birth_date_and_age"] = 82000,
["Birth_year_and_age"] = 7800,
["Blist"] = 2700,
["Block"] = 4300,
["Block/styles.css"] = 4800,
["Blocked_sockpuppet"] = 15000,
["Blocked_user"] = 18000,
["Blocked_userpage_check_protection"] = 36000,
["Blp"] = 3900,
["Blpsources"] = 3600,
["Bo"] = 2500,
["Bo/raw"] = 2500,
["Bookcover"] = 2700,
["Border"] = 2500,
["Border-radius"] = 5700,
["Bot-directive-archiver"] = 3300,
["Both"] = 336000,
["Bots"] = 2500,
["Box-shadow"] = 3400,
["Br_separated_entries"] = 281000,
["Break"] = 7300,
["Broken_anchor"] = 6300,
["Broken_anchors"] = 6800,
["Bronze3"] = 2700,
["Bulleted_list"] = 5000,
["Module:Babel"] = 5000,
["Module:BaseConvert"] = 31000,
["Module:Baseball_color"] = 4300,
["Module:Baseball_color/data"] = 3200,
["Module:Based_on"] = 3800,
["Module:BigNumber"] = 7600,
["Module:BigNumber/utils"] = 7600,
["Module:Break"] = 7300,
["Module:Buffer"] = 404000,
}
2f76b71f99830169d7c0f1270ecf35b102731663
Module:Transclusion count/data/I
828
135
278
2024-07-28T19:52:47Z
zhwp>A2093064-bot
0
[[User:A2093064-bot/task/44|機器人44]]:更新模板使用量
Scribunto
text/plain
return {
["ICounter"] = 9200,
["IDN"] = 4700,
["IMDb_name"] = 14000,
["IMDb_title"] = 16000,
["IND"] = 9800,
["IPA"] = 49000,
["IPA-fr"] = 38000,
["IPA/styles.css"] = 49000,
["IPA_audio_link"] = 8800,
["IPAc-en"] = 3200,
["IRL"] = 2300,
["IRN"] = 2800,
["ISBN"] = 12000,
["ISODate"] = 6400,
["ISO_3166_code"] = 100000,
["ISO_639_name"] = 396000,
["ISO_639_name_de"] = 23000,
["ISO_639_name_el"] = 2600,
["ISO_639_name_en"] = 244000,
["ISO_639_name_es"] = 16000,
["ISO_639_name_fr"] = 17000,
["ISO_639_name_hu"] = 2900,
["ISO_639_name_it"] = 3800,
["ISO_639_name_ja"] = 102000,
["ISO_639_name_ja-latn"] = 4700,
["ISO_639_name_ko"] = 23000,
["ISO_639_name_ko-hang"] = 4200,
["ISO_639_name_ko-hani"] = 3500,
["ISO_639_name_ko-latn"] = 4000,
["ISO_639_name_la"] = 80000,
["ISO_639_name_mn"] = 2200,
["ISO_639_name_nan"] = 3500,
["ISO_639_name_pinyin"] = 3200,
["ISO_639_name_pt"] = 8200,
["ISO_639_name_ru"] = 11000,
["ISO_639_name_th"] = 2100,
["ISO_639_name_uk"] = 2100,
["ISO_639_name_vi"] = 5900,
["ISO_639_name_vi-hani"] = 3600,
["ISO_639_name_yue"] = 2000,
["ISO_639_name_zh"] = 54000,
["ISR"] = 3100,
["ISSN_link"] = 2800,
["ITA"] = 15000,
["ITNtalk"] = 5500,
["ITNtalk/date"] = 5500,
["IUCN"] = 4100,
["Icon"] = 56000,
["If"] = 12000,
["IfFlow"] = 2000,
["IfIP"] = 4500,
["IfPNS"] = 666000,
["If_both"] = 5400,
["If_declined"] = 16000,
["If_empty"] = 603000,
["If_in_page"] = 676000,
["If_mobile"] = 64000,
["If_mobile/styles.css"] = 88000,
["If_pagename"] = 604000,
["If_preview"] = 48000,
["If_subst"] = 744000,
["If_then_show"] = 4300,
["IfdFileInfo"] = 3300,
["IfdLinkNext"] = 9200,
["IfdLinkToday"] = 3000,
["IfdLinkToday/auto"] = 2000,
["IfdUploader"] = 3300,
["Ifempty"] = 37000,
["Ifexist_not_redirect"] = 3100,
["Ifnumber"] = 27000,
["Ifsubst"] = 766000,
["Illinois-geo-stub"] = 4200,
["Image"] = 14000,
["Image_label"] = 3000,
["Image_label_begin"] = 2500,
["Image_other"] = 68000,
["Image_requested"] = 2100,
["Imbox"] = 68000,
["Imbox/style.css"] = 68000,
["Imdb_name"] = 4300,
["Imdb_title"] = 7100,
["Importance"] = 577000,
["Importance-col"] = 577000,
["Importance_mask"] = 647000,
["Importancecol"] = 577000,
["In_lang"] = 3400,
["Include-USGov"] = 5100,
["Increase"] = 6700,
["Indef"] = 12000,
["Indefblockeduser"] = 4000,
["Indiana-geo-stub"] = 3800,
["Infobox"] = 688000,
["Infobox3cols"] = 17000,
["Infobox_China_County"] = 3000,
["Infobox_China_railway_station"] = 6300,
["Infobox_Chinese/Footer"] = 5800,
["Infobox_Chinese/Header"] = 5800,
["Infobox_Chinese/Korean"] = 4000,
["Infobox_City"] = 3700,
["Infobox_Company"] = 6000,
["Infobox_EPW"] = 5900,
["Infobox_Film"] = 6800,
["Infobox_French_commune"] = 31000,
["Infobox_French_former_commune"] = 2400,
["Infobox_Indian_jurisdiction"] = 4500,
["Infobox_Italian_comune"] = 7600,
["Infobox_Korean_name"] = 3600,
["Infobox_Korean_name/categories"] = 3600,
["Infobox_Military_Conflict"] = 2900,
["Infobox_NBA_Player"] = 2200,
["Infobox_Officeholder"] = 6800,
["Infobox_PRCG"] = 3000,
["Infobox_Person"] = 3700,
["Infobox_Reservoir"] = 2100,
["Infobox_Roman_Catholic_diocese"] = 2900,
["Infobox_School"] = 3400,
["Infobox_Settlement"] = 8700,
["Infobox_Single"] = 2500,
["Infobox_Television"] = 4400,
["Infobox_VG"] = 5200,
["Infobox_Weapon"] = 2300,
["Infobox_airport"] = 2000,
["Infobox_album"] = 9600,
["Infobox_album/color"] = 13000,
["Infobox_album/link"] = 9600,
["Infobox_animanga/Collapsible"] = 6100,
["Infobox_animanga/CustomItem"] = 6900,
["Infobox_animanga/Footer"] = 6900,
["Infobox_animanga/Footerofja"] = 6700,
["Infobox_animanga/Head"] = 6900,
["Infobox_animanga/Header2"] = 6900,
["Infobox_animanga/Headerofja"] = 6800,
["Infobox_animanga/Image"] = 6600,
["Infobox_animanga/Item"] = 6900,
["Infobox_animanga/Manga"] = 4200,
["Infobox_animanga/TVAnime"] = 3200,
["Infobox_animanga/name"] = 2900,
["Infobox_award"] = 2100,
["Infobox_badminton_event"] = 2200,
["Infobox_badminton_player"] = 2600,
["Infobox_baseball_biography"] = 4300,
["Infobox_baseball_biography/style"] = 4300,
["Infobox_basketball_biography"] = 3900,
["Infobox_basketball_biography/style"] = 4000,
["Infobox_body_of_water"] = 3400,
["Infobox_book"] = 4300,
["Infobox_building"] = 5700,
["Infobox_bus_route"] = 2500,
["Infobox_company"] = 14000,
["Infobox_country"] = 2700,
["Infobox_country/formernext"] = 3200,
["Infobox_country/imagetable"] = 2400,
["Infobox_country/multirow"] = 4200,
["Infobox_country_at_games"] = 2400,
["Infobox_designation_list"] = 3900,
["Infobox_designation_list/entry"] = 3400,
["Infobox_diocese"] = 3200,
["Infobox_drug"] = 2100,
["Infobox_drug/chemical_formula"] = 2100,
["Infobox_drug/data_page_link"] = 2100,
["Infobox_drug/formatATC"] = 2100,
["Infobox_drug/formatChEBI"] = 2100,
["Infobox_drug/formatChEMBL"] = 2100,
["Infobox_drug/formatChemDBNIAID"] = 2100,
["Infobox_drug/formatChemSpider"] = 2100,
["Infobox_drug/formatCompTox"] = 2100,
["Infobox_drug/formatDrugBank"] = 2100,
["Infobox_drug/formatIUPHARBPS"] = 2100,
["Infobox_drug/formatJmol"] = 2100,
["Infobox_drug/formatKEGG"] = 2100,
["Infobox_drug/formatPubChemCID"] = 2100,
["Infobox_drug/formatPubChemSID"] = 2100,
["Infobox_drug/formatUNII"] = 2100,
["Infobox_drug/legal_status"] = 2100,
["Infobox_drug/licence"] = 2100,
["Infobox_drug/maintenance_categories"] = 2100,
["Infobox_drug/pregnancy_category"] = 2100,
["Infobox_drug/title"] = 2100,
["Infobox_entertainer"] = 2700,
["Infobox_film"] = 6700,
["Infobox_football_biography"] = 14000,
["Infobox_football_club"] = 3400,
["Infobox_former_subdivision"] = 2000,
["Infobox_historic_site"] = 3300,
["Infobox_lake"] = 3000,
["Infobox_language"] = 2300,
["Infobox_language/family-color"] = 2700,
["Infobox_language/linguistlist"] = 2300,
["Infobox_language/vitality"] = 2600,
["Infobox_language/vitality-short"] = 2600,
["Infobox_mapframe"] = 98000,
["Infobox_medal_templates"] = 31000,
["Infobox_military_conflict"] = 5700,
["Infobox_military_person"] = 3300,
["Infobox_military_unit"] = 2800,
["Infobox_mountain"] = 2200,
["Infobox_museum"] = 2000,
["Infobox_musical_artist"] = 3300,
["Infobox_musical_artist/hCard_class"] = 12000,
["Infobox_officeholder"] = 27000,
["Infobox_officeholder/office"] = 30000,
["Infobox_organization"] = 3500,
["Infobox_person"] = 33000,
["Infobox_person/Wikidata"] = 29000,
["Infobox_person/core"] = 33000,
["Infobox_person/height"] = 20000,
["Infobox_person/height/locate"] = 20000,
["Infobox_person/height/switch"] = 20000,
["Infobox_person/weight"] = 5200,
["Infobox_person/weight/locate"] = 5200,
["Infobox_person/weight/switch"] = 5200,
["Infobox_planet"] = 13000,
["Infobox_political_party"] = 2800,
["Infobox_rail_system-route"] = 3600,
["Infobox_religious_building"] = 4500,
["Infobox_religious_building/color"] = 4600,
["Infobox_religious_building/count"] = 4500,
["Infobox_reservoir"] = 2100,
["Infobox_river"] = 3100,
["Infobox_river/source"] = 3100,
["Infobox_road2"] = 4200,
["Infobox_road2/hide/tourist"] = 4200,
["Infobox_road2/meta/errors"] = 4300,
["Infobox_road2/meta/mask/country"] = 4200,
["Infobox_royalty"] = 5800,
["Infobox_school"] = 4800,
["Infobox_scientist"] = 5600,
["Infobox_settlement"] = 203000,
["Infobox_settlement/areadisp"] = 129000,
["Infobox_settlement/columns"] = 38000,
["Infobox_settlement/densdisp"] = 197000,
["Infobox_settlement/impus"] = 4900,
["Infobox_settlement/lengthdisp"] = 61000,
["Infobox_settlement/link"] = 38000,
["Infobox_settlement/metric"] = 141000,
["Infobox_settlement/metric_only"] = 2700,
["Infobox_settlement/pref"] = 149000,
["Infobox_settlement_YS"] = 2500,
["Infobox_software"] = 3600,
["Infobox_song"] = 7600,
["Infobox_song/color"] = 7600,
["Infobox_song/link"] = 7600,
["Infobox_sportsperson"] = 5600,
["Infobox_sportsperson/core"] = 5600,
["Infobox_station"] = 33000,
["Infobox_street"] = 3400,
["Infobox_street/meta/length"] = 2200,
["Infobox_television"] = 5800,
["Infobox_university"] = 6200,
["Infobox_venue"] = 2100,
["Infobox_weapon"] = 3200,
["Infobox_writer"] = 4100,
["Infobox_羽球選手"] = 2500,
["Information"] = 9400,
["Infraspeciesbox"] = 4700,
["Infraspeciesbox/italic_check"] = 4700,
["Infraspeciesbox/search_wikidata"] = 5000,
["Instagram"] = 16000,
["Internal_link_helper/de"] = 13000,
["Internal_link_helper/en"] = 315000,
["Internal_link_helper/es"] = 6200,
["Internal_link_helper/fr"] = 15000,
["Internal_link_helper/it"] = 4000,
["Internal_link_helper/ja"] = 62000,
["Internal_link_helper/ko"] = 16000,
["Internal_link_helper/nl"] = 3000,
["Internal_link_helper/pl"] = 2900,
["Internal_link_helper/pt"] = 4100,
["Internal_link_helper/ru"] = 10000,
["Internal_link_helper/uk"] = 12000,
["Internal_link_helper/vi"] = 3500,
["Internal_link_helper/yue"] = 5000,
["Iowa-geo-stub"] = 2900,
["IsIP"] = 4700,
["Is_article"] = 10000,
["Is_italic_taxon"] = 180000,
["Isnumeric"] = 5900,
["Module:I18n"] = 185000,
["Module:I18n/complex_date"] = 30000,
["Module:I18n/date"] = 30000,
["Module:IPAc-en"] = 3200,
["Module:IPAc-en/data"] = 3200,
["Module:IPAc-en/phonemes"] = 3200,
["Module:IPAc-en/pronunciation"] = 3200,
["Module:IPAddress"] = 5200,
["Module:ISODate"] = 2800,
["Module:ISO_3166"] = 100000,
["Module:ISO_3166/data/National"] = 100000,
["Module:ISO_3166/data/US"] = 43000,
["Module:ISOdate"] = 30000,
["Module:Icon"] = 56000,
["Module:Icon/data"] = 56000,
["Module:IfUtil"] = 163000,
["Module:If_empty"] = 603000,
["Module:If_in_page"] = 676000,
["Module:If_mobile"] = 88000,
["Module:If_preview"] = 227000,
["Module:If_preview/configuration"] = 227000,
["Module:If_preview/styles.css"] = 227000,
["Module:Ilh"] = 509000,
["Module:Ilh/data"] = 509000,
["Module:Importance/convert"] = 657000,
["Module:Importance/data"] = 657000,
["Module:In_lang"] = 3400,
["Module:Infobox"] = 722000,
["Module:Infobox/styles.css"] = 688000,
["Module:Infobox3cols"] = 17000,
["Module:InfoboxImage"] = 647000,
["Module:InfoboxImageVariant"] = 29000,
["Module:InfoboxImageVariant2"] = 5200,
["Module:Infobox_VG"] = 5200,
["Module:Infobox_artist"] = 3600,
["Module:Infobox_artist/parameterListCV"] = 2300,
["Module:Infobox_mapframe"] = 103000,
["Module:Infobox_military_conflict"] = 5700,
["Module:Infobox_military_conflict/styles.css"] = 5700,
["Module:Infobox_road2"] = 4200,
["Module:Infobox_road2/color"] = 4200,
["Module:Infobox_road2/length"] = 4200,
["Module:Infobox_road2/locations"] = 4200,
["Module:Infobox_road2/map"] = 4200,
["Module:Italic_title"] = 33000,
}
41810e3b17a5b78e8a6ddab78320ce92d0663585
Module:Transclusion count/data/R
828
206
430
2024-07-28T19:54:17Z
zhwp>A2093064-bot
0
[[User:A2093064-bot/task/44|機器人44]]:更新模板使用量
Scribunto
text/plain
return {
["R"] = 16000,
["R/ref"] = 16000,
["RA"] = 11000,
["RMCategory"] = 7700,
["ROC"] = 25000,
["ROC-1912"] = 2100,
["ROC-TW"] = 8000,
["ROK"] = 3200,
["ROU"] = 2500,
["RUS"] = 11000,
["Rail-interchange"] = 15000,
["Rail-interchange/cn"] = 9000,
["Rail_color"] = 14000,
["Rail_pass_box"] = 3200,
["RankedMedalTable"] = 2100,
["Rcr"] = 13000,
["Rdt_intro"] = 3100,
["Re"] = 2200,
["Red"] = 3300,
["Redirect"] = 2800,
["Redirect_category_shell"] = 156000,
["Redirect_template"] = 508000,
["Redirect_template/st"] = 376000,
["Ref"] = 2300,
["Ref_label"] = 3700,
["Refbegin"] = 61000,
["Refend"] = 61000,
["Refimprove"] = 33000,
["Reflist"] = 982000,
["ReflistF"] = 64000,
["ReflistH"] = 65000,
["ReflistH/styles.css"] = 65000,
["Refnest"] = 4300,
["Refs"] = 2800,
["RegioneIT"] = 6000,
["RegioneIT_(coat_of_arms)"] = 6000,
["Registration_required"] = 17000,
["Remark"] = 7900,
["Remind"] = 3300,
["Remove_first_word"] = 34000,
["Replace"] = 15000,
["Reply"] = 21000,
["Reply_to"] = 21000,
["Resize"] = 26000,
["Rint"] = 14000,
["Rmr"] = 2600,
["Rnd"] = 128000,
["Rnd/-"] = 116000,
["Romania-geo-stub"] = 3100,
["Rotten-tomatoes"] = 4400,
["Rotten_Tomatoes"] = 6300,
["Rough_translation"] = 6000,
["Roughtranslation"] = 2500,
["Rounddown"] = 4800,
["Routemap"] = 9200,
["Routemap/styles.css"] = 11000,
["RoutemapRoute"] = 4200,
["Rp"] = 14000,
["Ru_icon"] = 3200,
["Ruby"] = 2400,
["Ruby/styles.css"] = 2500,
["Russia-geo-stub"] = 5100,
["Russia-stub"] = 2700,
["Module:Redirect"] = 64000,
["Module:Redirect_category_shell"] = 156000,
["Module:Redirect_hatnote"] = 3000,
["Module:Redirect_template"] = 508000,
["Module:Reply_to"] = 26000,
["Module:ResolveEntityId"] = 120000,
["Module:Road_data/extra"] = 2400,
["Module:Road_data/parser"] = 2700,
["Module:Roman"] = 31000,
["Module:RouteSequence"] = 14000,
["Module:Routemap"] = 11000,
}
57fa4d820f05479ac73afddd42b7638f09e3a09a
Module:Transclusion count/data/U
828
278
580
2024-07-28T19:54:47Z
zhwp>A2093064-bot
0
[[User:A2093064-bot/task/44|機器人44]]:更新模板使用量
Scribunto
text/plain
return {
["UK"] = 7000,
["UKR"] = 3900,
["URL"] = 52000,
["URS"] = 4700,
["US"] = 2900,
["USA"] = 37000,
["USSR"] = 2700,
["US_county_navigation_box"] = 50000,
["US_county_navigation_box/core"] = 50000,
["US_state_navigation_box"] = 3100,
["UTC+8"] = 2400,
["Ubl"] = 18000,
["Unblock"] = 4200,
["Unbulleted_list"] = 55000,
["Unicode"] = 5400,
["Unlink"] = 2100,
["Unping"] = 4400,
["Unreferenced"] = 65000,
["Update"] = 4800,
["Uploader_information"] = 22000,
["Url"] = 18000,
["User"] = 48000,
["User_Google"] = 2500,
["User_UTC"] = 2600,
["User_UTC+8"] = 2200,
["User_en-2"] = 2500,
["User_en-3"] = 2600,
["User_language-1"] = 5000,
["User_language-2"] = 5200,
["User_language-3"] = 4600,
["User_language-4"] = 2800,
["User_language-N"] = 9700,
["User_male"] = 2500,
["User_other"] = 9200,
["User_zh"] = 6100,
["Userbox"] = 31000,
["Userbox-2"] = 9100,
["Userbox-level"] = 3400,
["Userbox-r"] = 2100,
["Userboxbottom"] = 4300,
["Userboxtop"] = 4800,
["Userpage"] = 2700,
["Uses_Lua"] = 3000,
["Usgs-gazetteer"] = 4800,
["Module:URL"] = 84000,
["Module:Unicode_data"] = 490000,
["Module:Unicode_data/scripts"] = 55000,
["Module:Unsubst"] = 154000,
["Module:Unsubst-infobox"] = 17000,
["Module:Unsubst2"] = 4900,
["Module:Userbox"] = 32000,
["Module:Ustring"] = 48000,
}
5a8b434ed0393c9a247cb54549279bb88f201158
Template:Fix/category
10
273
568
2024-07-31T20:51:38Z
zhwp>Xiplus-abot
0
已更改“[[Template:Fix/category]]”的保护设置:高風險模板:100037引用<!-- [[User:Xiplus-abot/task/3|機器人3]] -->([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{{cat|<includeonly>[[Category:需要清理的条目]]</includeonly>}}}{{#if:{{{cat-date|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}{{#if:{{{cat2|}}}|{{{cat2}}}}}{{#if:{{{cat-date2|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date2}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date2}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}{{#if:{{{cat3|}}}|{{{cat3}}}}}{{#if:{{{cat-date3|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date3}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date3}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}
5aba2c0a3df1f67b5f8d45eb6c2506f0b99faebc
首页
0
1
1
2024-08-02T02:54:00Z
MediaWiki default
1
欢迎来到Miraheze!
wikitext
text/x-wiki
__NOTOC__
== 欢迎来到 {{SITENAME}}! ==
该首页由接受请求的志愿者——Wiki 建立者自动建立,而且内容似乎尚未更改。
=== 如果您是本站的行政员 ===
您好,欢迎来到您的新 Wiki!感谢您选择 Miraheze 作为您的 Wiki 平台,我们真诚地希望您能够享受我们的服务。
只要您愿意,您随时可以开始在本维基上进行工作。
需要帮助?没问题!如有需要,我们当然乐于效劳。作为开始,下面是几个关于在 MediaWiki 上面进行工作的链接:
* <span class="plainlinks">[https://www.mediawiki.org/wiki/Help:Contents MediaWiki 手册(例如浏览、编辑、删除页面、封禁用户等)]</span>
* <span class="plainlinks">[https://meta.miraheze.org/wiki/FAQ Miraheze 常见问题]</span>
* <span class="plainlinks">[https://meta.miraheze.org/wiki/Request_features 请求在自己的 Wiki 上面加入扩展、修改
Logo/favicon 或引入其他功能]</span>
==== 但是……有些问题我仍然不懂! ====
那也没关系,即使文档或 FAQ 上面没写,我们也愿意提供帮助。您可以通过以下途径联系我们:
* <span class="plainlinks">[https://meta.miraheze.org/wiki/Help_center Miraheze Wiki 帮助中心]</span>
* IRC 频道 #miraheze(服务器为 irc.libera.chat。[irc://irc.libera.chat/%23miraheze 直接连接]、[https://web.libera.chat/?channel=#miraheze 网页聊天室])
=== 如果您是游客 ===
您好,本页是系统默认生成的首页,目前尚未被本站的行政员修改。他们可能正在制作首页,所以请您稍后再来。
4c2075b07662210c2f9bf0e4cdd8dfab6aaf3a2a
8
1
2024-08-02T06:45:33Z
黑茶
2
已保护“[[首页]]”([编辑=仅允许管理员](无限期)[移动=仅允许管理员](无限期))[连锁保护]
wikitext
text/x-wiki
__NOTOC__
== 欢迎来到 {{SITENAME}}! ==
该首页由接受请求的志愿者——Wiki 建立者自动建立,而且内容似乎尚未更改。
=== 如果您是本站的行政员 ===
您好,欢迎来到您的新 Wiki!感谢您选择 Miraheze 作为您的 Wiki 平台,我们真诚地希望您能够享受我们的服务。
只要您愿意,您随时可以开始在本维基上进行工作。
需要帮助?没问题!如有需要,我们当然乐于效劳。作为开始,下面是几个关于在 MediaWiki 上面进行工作的链接:
* <span class="plainlinks">[https://www.mediawiki.org/wiki/Help:Contents MediaWiki 手册(例如浏览、编辑、删除页面、封禁用户等)]</span>
* <span class="plainlinks">[https://meta.miraheze.org/wiki/FAQ Miraheze 常见问题]</span>
* <span class="plainlinks">[https://meta.miraheze.org/wiki/Request_features 请求在自己的 Wiki 上面加入扩展、修改
Logo/favicon 或引入其他功能]</span>
==== 但是……有些问题我仍然不懂! ====
那也没关系,即使文档或 FAQ 上面没写,我们也愿意提供帮助。您可以通过以下途径联系我们:
* <span class="plainlinks">[https://meta.miraheze.org/wiki/Help_center Miraheze Wiki 帮助中心]</span>
* IRC 频道 #miraheze(服务器为 irc.libera.chat。[irc://irc.libera.chat/%23miraheze 直接连接]、[https://web.libera.chat/?channel=#miraheze 网页聊天室])
=== 如果您是游客 ===
您好,本页是系统默认生成的首页,目前尚未被本站的行政员修改。他们可能正在制作首页,所以请您稍后再来。
4c2075b07662210c2f9bf0e4cdd8dfab6aaf3a2a
那艺娜维基:上传
4
2
2
2024-08-02T05:15:54Z
黑茶
2
创建页面,内容为“上传”
wikitext
text/x-wiki
上传
a977650db1aef245545276141f8f0a114e371ffd
MediaWiki:Group-超级管理员-member
8
3
3
2024-08-02T05:22:55Z
黑茶
2
创建页面,内容为“[[那艺娜维基:超级管理员|超级管理员]]”
wikitext
text/x-wiki
[[那艺娜维基:超级管理员|超级管理员]]
93137ace3c3d11766bed48518ed6d50ef599d07c
4
3
2024-08-02T05:34:11Z
黑茶
2
wikitext
text/x-wiki
{{GENDER:$1|管理员}}
8587a23a36612c17abc7509d48712327d4765ce3
5
4
2024-08-02T05:34:45Z
黑茶
2
wikitext
text/x-wiki
{{GENDER:$1|超级管理员}}
8f303d25d226ca109d43f52546f832874b1e5679
MediaWiki:Nstab-lta
8
4
6
2024-08-02T05:43:21Z
黑茶
2
创建页面,内容为“持续出没的破坏者”
wikitext
text/x-wiki
持续出没的破坏者
6c2dce566556f376783ce2eb785776351a4f3e29
那艺娜维基:超级管理员
4
5
7
2024-08-02T06:30:56Z
黑茶
2
创建页面,内容为“'''超级管理员'''是本维基最强大的权限”
wikitext
text/x-wiki
'''超级管理员'''是本维基最强大的权限
a716765a049affe47476ac58a93af68e1bf09c1d
MediaWiki:Grouppage-超级管理员
8
6
9
2024-08-02T06:53:14Z
黑茶
2
创建页面,内容为“那艺娜维基:超级管理员”
wikitext
text/x-wiki
那艺娜维基:超级管理员
1ad7df73415428feb37ac6c81dffccb37774ae6a
那艺娜维基:沙盒
4
8
11
2024-08-02T07:04:30Z
111.38.48.80
0
[[WP:AES|←]]页面内容被替换为“{{請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。}} {{请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。}}”
wikitext
text/x-wiki
{{請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。}}
{{请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。}}
501961ae6665b389fd9d46de961123725886aa5c
12
11
2024-08-02T10:36:24Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。}}
{{请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。}}
501961ae6665b389fd9d46de961123725886aa5c
那艺娜维基:Lan
4
9
14
13
2024-08-02T10:36:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:lan|main}}</includeonly><noinclude>{{模板文档}}</noinclude>
9a0c6ae29e4b3d5782f1580fbccc37393902b49f
那艺娜维基:No redirect
4
10
16
15
2024-08-02T10:36:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}|{{{2}}}]]|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}]]}}
}}<noinclude>{{lua|Module:Redirect}}
{{documentation}}
</noinclude>
996c1e73b0906e1e05cab3f9aaff13ea04646ff8
那艺娜维基:Fullurl
4
11
18
17
2024-08-02T10:36:27Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span class="plainlinks">[{{fullurl:{{{1}}}|{{{2}}}}} {{{3}}}]</span><noinclude>
{{documentation}}</noinclude>
9c51dda6ddd9f9055ed3843b256871781d737593
那艺娜维基:If mobile
4
12
20
19
2024-08-02T10:36:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:If mobile|main}}<noinclude>
{{Documentation}}</noinclude>
704e8b891b9980b01d12ed061de7486c87b2274b
那艺娜维基:If mobile/styles.css
4
13
22
21
2024-08-02T10:36:28Z
黑茶
2
导入1个版本
sanitized-css
text/css
/* Because of how TemplateStyles and MobileFrontend work, it's not possible to
directly test for whether the mobile site is being used in a TemplateStyle. As
such we'll use Minerva as a proxy. This is imperfect. */
body:not(.skin-minerva) .ifmobile > .mobile {
display: none;
}
/*
Force nomobile element to display when present.
Overrides skin-based css for hiding the nomobile class, e.g. Timeless skin with screen size less than 850px.
*/
body.skin-minerva .ifmobile > .nomobile {
display: inherit; /* The fallback */
display: initial;
}
64e9502c6c99627f7760022c2c8ecd83e3699f4a
那艺娜维基:Div col
4
14
24
23
2024-08-02T10:36:29Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{cols|{{{1|}}}}}}{{{colwidth|{{{2|}}}}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{cols|{{{1|}}}}}}|column-count:{{{cols|{{{1|}}}}}}; column-width:auto;<!-- 用以覆盖[[T:Div col/styles.css]]中预设的列宽“30em”,使列数不受其影响 -->}}{{#if:{{{colwidth|{{{2|}}}}}}|column-width:{{{colwidth|{{{2|}}}}}};}}{{#if:{{{gap|}}}|column-gap:{{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
--><!--{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}--><!--
--></includeonly><!--{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}--><noinclude>
{{Documentation}}
</noinclude>
b9f1dd532f74d3c57839cafc7017868d579f8880
那艺娜维基:Div col/styles.css
4
15
26
25
2024-08-02T10:36:29Z
黑茶
2
导入1个版本
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
/* Unbulleted lists */
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
76c2c0a042b9164cff638cd44af5ab129702c141
那艺娜维基:Div col end
4
16
28
27
2024-08-02T10:36:29Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly></div></includeonly><noinclude>
{{Documentation|Template:Div col/doc}}
</noinclude>
78088d41c21d779e3722f220fcc9773dfbbc1e4f
那艺娜维基:Fullurl2
4
17
30
29
2024-08-02T10:36:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:fullurl|fullurl}}<noinclude>
{{doc}}</noinclude>
bcec16f0cb14ffd7fbc29d4efa40670958541c85
那艺娜维基:Void
4
18
32
31
2024-08-02T10:36:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{doc}}</noinclude>
2ad0a7aac7bb5b51850ca5d508fcde851272e224
那艺娜维基:Shortcut
4
19
34
33
2024-08-02T10:36:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>{{Documentation}}</noinclude>
366b7fa8a7ebad556d8ab80288b32d97172cef80
那艺娜维基:Shortcut/styles.css
4
20
36
35
2024-08-02T10:36:32Z
黑茶
2
导入1个版本
sanitized-css
text/css
.shortcutbox {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.shortcutbox-left {
float:left;
}
.shortcutbox-ombox {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.shortcut-anchordiv {
position:relative;
top:-3em;
}
.module-shortcutboxplain {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.module-shortcutboxplain-left {
float:left;
}
.module-omboxshortcutplain {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.module-shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.module-shortcutanchordiv {
position:relative;
top:-3em;
}
9c4ef4c581a945084d5e44c5b35135cef5ea8c27
那艺娜维基:請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。
4
21
38
37
2024-08-02T10:36:33Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Sandbox heading]]
623db2a6ae7dc15c833cef604ced75a5c2e01189
那艺娜维基:Sandbox heading
4
22
40
39
2024-08-02T10:36:34Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<!--
简体中文
注意:这不是一个沙盒!!!
这是一个放置于沙盒顶端的模板。
如果你想练习编辑,请不要在这个模板上进行。
你可以通过在搜索中输入“WP:S”或“WP:Temp”或“WP:SB”或“Wikipedia:沙盒”找到真正的沙盒
如果你想在模板空间测试,请前往 “Template:沙盒” 或 “Template:X1” 和 “Template:X2”
再次申明,这个模版不是用于试验的!
这个沙盒模版位于:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><!--
繁體中文
注意:這不是一個沙盒!!!
這是一個放置於沙盒頂端的模板。
如果你想練習編輯,請不要在這個模板上進行。
你可以透過在搜尋中輸入「WP:Temp」或「WP:SB」或「Wikipedia:沙盒」找到真正的沙盒
如果你想在模板空間測試,請前往「WP:S」或「Template:沙盒」或「Template:X1」和「Template:X2」
再次申明,這個模板不是用於試驗的!
這個沙盒模板位於:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><noinclude>{{About|置于沙盒顶端的提示-{zh-hant:資訊; zh-hans:信息;}-。'''本模板本身不是沙盒'''|用于测试的模板沙盒|模板:沙盒}}{{nottest}}</noinclude><includeonly>__NOINDEX__</includeonly>
{{noEdit}}
<!-- 不应修改沙盒的首段 - 首段包含对此模板的引用 -->
<div class="messagebox plainlinks" style="padding: 10px; margin: 20px auto; width: 100%; font-size: 10pt;background-color:var(--background-color-interactive-subtle,#f8f9fa);color: inherit;">
{|
|-
||[[File:Edit_In_Sandbox_Icon_-_Color.svg|75px|left|alt=|link=]]
||<big>欢迎来到'''[[Wikipedia:关于沙盒|维基百科沙盒]]'''!</big>
{{{editnotice|
如果{{lan|zh-hans=您|zh-hant=您|zh-hk=閣下}}想要在此測試,請{{Fullurl|1={{FULLPAGENAME}}|2=action=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}或上方的{{If mobile|'''鉛筆{{lan|zh-hans=图标|zh-hant=圖示}}'''|{{#if:{{{1|}}}||'''編輯{{lan|zh-cn=源代码|zh-sg=原始码|zh-tw=原始碼}}'''}}}}即可,也可{{Fullurl|1={{FULLPAGENAME}}|2=veaction=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}使用[[WP:VE|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]]進行編輯。}}}
沙盒是用于练习页面编辑技巧的測試页面。您可在此随意地进行编辑的练习。完成编辑后,可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Showpreview}}'''”按钮预览内容,也可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Publishchanges}}'''”按钮{{lan|zh-cn=保存|zh-tw=儲存}}内容。就像在沙灘上所寫的文字涨潮时就會消失,同样沙盒中所寫的內容,隨時可能被清空,不會有任何預先通知(但曾{{lan|zh-cn=保存|zh-tw=儲存}}的内容仍会永久存留在页面的历史记录中)。
||
{{#switch: {{FULLPAGENAME}}
| Wikipedia:沙盒 = {{Shortcut|WP:S|WP:SB|WP:SAND|WP:TMP|WP:TEST|WP:FOO}}<!--
| Template:沙盒 = {{Shortcut|T:SB}} -->
| Template:X1 = {{Shortcut|T:X1}}
| Template:X2 = {{Shortcut|T:X2}}
| Template:X3 = {{Shortcut|T:X3}}
| Category:沙盒 = {{Shortcut|CAT:SB}}
| 模块:沙盒 = {{Shortcut|Module:SB}}
| Draft:沙盒 = {{Shortcut|Draft:SB}}
| Template:沙盒/test.css = {{Shortcut|T:SB/CSS}}
}}
|}
{{columns|bgcol=transparent;width:100%|width=50%
|col1 = '''注意事项''':
* '''不要'''在公用的沙盒撰写条目或存放其他有价值的内容(請参考[[Help:创建新条目|{{lan|zh-cn=创建|zh-tw=建立}}新页面]]及[[WP:WIZ|{{lan|zh-cn=创建|zh-tw=建立}}条目向导]]);
* '''不要'''在沙盒{{lan|zh-cn=里|zh-hk=裏|zh-tw=裡}}{{lan|zh-cn=保存|zh-tw=儲存}}有侵犯他人版权、攻击性、诽谤中伤他人或他人隱私的内容;
* '''不要'''将沙盒[[Wikipedia:重定向|{{lan|zh-cn=重定向|zh-tw=重新導向}}]]至别的页面,或将顶部模板移除;
* '''不要'''在沙盒進行廣告宣傳或刷编辑次数,否則可能會被[[Wikipedia:封禁方针|{{lan|zh-hans=封禁|zh-hant=封鎖}}]];
* 歡迎參考[[Wikipedia:常见问题解答|常見問題解答]]及[[Wikipedia:新手入門/主頁|使用指南]];
* 如果对[[维基百科]]有任何问题,請到[[Wikipedia:互助客栈|互助客栈]]询问。
|col2 = '''工具''':
{{div col|cols=2}}
* [[Wikipedia:沙盒|主沙盒]]
** {{fullurl2|Wikipedia:沙盒|action=edit|原始碼編輯}}
** {{fullurl2|Wikipedia:沙盒|veaction=edit|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯}}
* {{noredirect|Wikipedia:重定向沙盒|{{lan|zh-cn=重定向|zh-tw=重新導向}}沙盒}}
* [[User:沙盒页|{{lan|zh-cn=用户页|zh-tw=使用者頁面}}沙盒]]
* [[Template:沙盒|模板測試沙盒]]([[Template:X1|X1]]、[[Template:X2|X2]]、[[Template:X3|X3]]、[[Template:沙盒/TemplateStyles|TS]])
* [[Template:沙盒/TemplateStyles|模板樣式總測試沙盒]]
* [[:Category:沙盒|分類測試沙盒]]
* 圖片測試沙盒:[[:File:沙盒.png|PNG]]、[[:File:沙盒.svg|SVG]]
* [[User talk:Sandbox for user warnings~zhwiki|对话页測試沙盒]]([[User talk:Sandbox for user warnings~zhwiki~Flow|Flow版]])
* [[Module:沙盒|{{lan|zh-hans=模块|zh-hant=模組}}總測試沙盒]]
* [[Wikipedia talk:Flow tests|Flow對話沙盒]]
* [{{fullurl:Draft:沙盒|veaction=edit}} {{lan|zh-hans=可视化|zh-hant=視覺化}}编辑器沙盒]
* [[WP:Huggle/Sandbox|Huggle沙盒]]
* [[Special:ApiSandbox|API沙盒]]
* 維基數據沙盒:[[:d:Q4115189|1]]、[[:d:Q13406268|2]]、[[:d:Q15397819|3]]、[[:d:Q112795079|4]]
* [[testwiki:|測試維基]]
* [[mw:Project:Sandbox|MediaWiki沙盒]]([[mw:VisualEditor:Test|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]])
* [{{fullurl:Special:Mypage/沙盒|action=edit&preload=Template:用戶沙盒/preload}} 您自己的沙盒]
* [[Wikipedia:關於沙盒|其他{{lan|zh-hans=资料|zh-hant=資料}}]]
{{div col end}}
}}
</div><div class="abusefilter-sandbox-header"></div><includeonly>
{{#switch:{{FULLPAGENAME}}
| Category:沙盒 = {{hiddencat}}
[[Category:維基百科管理]]
| #default = {{#ifeq:{{NAMESPACE}}|User||{{#ifeq:{{NAMESPACE}}|User talk||{{#if:{{{8|}}}||[[Category:沙盒]]}}}}}}
}}</includeonly>
{{{editnotice|
----}}}<noinclude>
{{doc}}
</noinclude>
f2ad992b81199261b0c806fb320939944a642b1a
那艺娜维基:NoEdit
4
23
42
41
2024-08-02T10:36:34Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#if:{{{|}}}<!--
产生没有编辑按钮的标题 -->|<div class="noedit">
={{{|}}}
</div><!--
编辑首段按钮不出现 -->|<span id="no-edit-0"></span><!--
结束 -->}}</includeonly><noinclude>
{{模板文档}}
</noinclude>
2908b829aa6bf620e236da30d2e5c6bc6c5b57d4
那艺娜维基:Columns
4
24
44
43
2024-08-02T10:36:34Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<templatestyles src="Columns/styles.css" /><table class="multicol skin-nightmode-reset-color" style="{{#switch:{{{align|}}}
|left|right=float:{{{align}}}
|center=margin:0.5em auto
}};border-spacing:0;background:{{{background|{{{bgcol|transparent}}}}}};{{#if:{{{text-align|}}}|text-align:{{{text-align}}};}}{{{style|}}}" role="presentation">
<tr style="vertical-align:top;">
<td style="width:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col1style|}}};">{{#ifeq:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col1}}}</td>
{{#if:{{{col2<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col2style|}}};">{{#ifeq:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col2}}}</td>
}}{{#if:{{{col3<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col3style|}}};">{{#ifeq:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col3}}}</td>
}}{{#if:{{{col4<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col4style|}}};">{{#ifeq:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col4}}}</td>
}}{{#if:{{{col5<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col5style|}}};">{{#ifeq:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col5}}}</td>
}}{{#if:{{{col6<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col6style|}}};">{{#ifeq:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col6}}}</td>
}}{{#if:{{{col7<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col7style|}}};">{{#ifeq:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col7}}}</td>
}}{{#if:{{{col8<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col8style|}}};">{{#ifeq:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col8}}}</td>
}}{{#if:{{{col9<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col9style|}}};">{{#ifeq:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col9}}}</td>
}}{{#if:{{{col10<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col10style|}}};">{{#ifeq:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col10}}}</td>
}}
</tr></table><noinclude>{{Documentation}}</noinclude>
3c43118d7fdd34f4c2eeb0eb1de02303f4435f19
那艺娜维基:Columns/styles.css
4
25
46
45
2024-08-02T10:36:35Z
黑茶
2
导入1个版本
sanitized-css
text/css
@media (min-width: 720px) {
.columns-start .column {
/* @noflip */
float: left;
min-width: 20em;
}
.columns-2 .column {
width: 50%;
}
.columns-3 .column {
width: 33.3%;
}
.columns-4 .column {
width: 25%;
}
.columns-5 .column {
width: 20%;
}
}
da82fb4f7604181dee3116fd03863f7fb2beb7ea
那艺娜维基:请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。
4
26
48
47
2024-08-02T10:36:35Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Void]]
90ff2dc1111160c936f3a960d5c2158a7628aed5
那艺娜维基:Noredirect
4
27
50
49
2024-08-02T10:36:36Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:No redirect]]
7bbca779757c40530991fa4afadd831104b1287e
Module:Yesno
828
28
52
51
2024-08-02T10:37:09Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- Function allowing for consistent treatment of boolean-like wikitext input.
-- It works similarly to the template {{yesno}}.
return function (val, default)
-- If your wiki uses non-ascii characters for any of "yes", "no", etc., you
-- should replace "val:lower()" with "mw.ustring.lower(val)" in the
-- following line.
val = type(val) == 'string' and val:lower() or val
if val == nil then
return nil
elseif val == true
or val == 'yes'
or val == 'y'
or val == 'true'
or val == 't'
or val == 'on'
or val == '是'
or val == '开'
or val == '開'
or tonumber(val) == 1
then
return true
elseif val == false
or val == 'no'
or val == 'n'
or val == 'false'
or val == 'f'
or val == 'off'
or val == '否'
or val == '关'
or val == '關'
or tonumber(val) == 0
then
return false
else
return default
end
end
2f0635fe93a396f2633055bc8670ccb84f3caa50
Module:Error
828
29
54
53
2024-08-02T10:37:10Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{error}}.
local p = {}
local function _error(args)
local message = args.message or args[1] or error('没有指定的-{zh-cn:信息; zh-tw:資訊}-', 2)
message = tostring(message)
local tag = mw.ustring.lower(tostring(args.tag))
-- Work out what html tag we should use.
if not (tag == 'p' or tag == 'span' or tag == 'div') then
tag = 'strong'
end
-- Generate the html.
local root = mw.html.create(tag)
root
:addClass('error')
:wikitext(message)
return tostring(root)
end
function p.error(frame)
local args
if frame == mw.getCurrentFrame() then
-- We're being called via #invoke. The args are passed through to the module
-- from the template page, so use the args that were passed into the template.
args = frame.args
else
-- We're being called from another module or from the debug console, so assume
-- the args are passed in directly.
args = frame
end
-- if the message parameter is present but blank, change it to nil so that Lua will
-- consider it false.
if args.message == "" then
args.message = nil
end
return _error(args)
end
return p
64a3fbd57daa8eebfa0f4febc68c915408fd272d
Module:Arguments
828
30
56
55
2024-08-02T10:37:10Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides easy processing of arguments passed to Scribunto from
-- #invoke. It is intended for use by other Lua modules, and should not be
-- called from #invoke directly.
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local arguments = {}
-- Generate four different tidyVal functions, so that we don't have to check the
-- options every time we call it.
local function tidyValDefault(key, val)
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
else
return val
end
else
return val
end
end
local function tidyValTrimOnly(key, val)
if type(val) == 'string' then
return val:match('^%s*(.-)%s*$')
else
return val
end
end
local function tidyValRemoveBlanksOnly(key, val)
if type(val) == 'string' then
if val:find('%S') then
return val
else
return nil
end
else
return val
end
end
local function tidyValNoChange(key, val)
return val
end
local function matchesTitle(given, title)
local tp = type( given )
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title
end
local translate_mt = { __index = function(t, k) return k end }
function arguments.getArgs(frame, options)
checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}
--[[
-- Set up argument translation.
--]]
options.translate = options.translate or {}
if getmetatable(options.translate) == nil then
setmetatable(options.translate, translate_mt)
end
if options.backtranslate == nil then
options.backtranslate = {}
for k,v in pairs(options.translate) do
options.backtranslate[v] = k
end
end
if options.backtranslate and getmetatable(options.backtranslate) == nil then
setmetatable(options.backtranslate, {
__index = function(t, k)
if options.translate[k] ~= k then
return nil
else
return k
end
end
})
end
--[[
-- Get the argument tables. If we were passed a valid frame object, get the
-- frame arguments (fargs) and the parent frame arguments (pargs), depending
-- on the options set and on the parent frame's availability. If we weren't
-- passed a valid frame object, we are being called from another Lua module
-- or from the debug console, so assume that we were passed a table of args
-- directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then
if options.wrappers then
--[[
-- The wrappers option makes Module:Arguments look up arguments in
-- either the frame argument table or the parent argument table, but
-- not both. This means that users can use either the #invoke syntax
-- or a wrapper template without the loss of performance associated
-- with looking arguments up in both the frame and the parent frame.
-- Module:Arguments will look up arguments in the parent frame
-- if it finds the parent frame's title in options.wrapper;
-- otherwise it will look up arguments in the frame object passed
-- to getArgs.
--]]
local parent = frame:getParent()
if not parent then
fargs = frame.args
else
local title = parent:getTitle():gsub('/sandbox$', '')
local found = false
if matchesTitle(options.wrappers, title) then
found = true
elseif type(options.wrappers) == 'table' then
for _,v in pairs(options.wrappers) do
if matchesTitle(v, title) then
found = true
break
end
end
end
-- We test for false specifically here so that nil (the default) acts like true.
if found or options.frameOnly == false then
pargs = parent.args
end
if not found or options.parentOnly == false then
fargs = frame.args
end
end
else
-- options.wrapper isn't set, so check the other options.
if not options.parentOnly then
fargs = frame.args
end
if not options.frameOnly then
local parent = frame:getParent()
pargs = parent and parent.args or nil
end
end
if options.parentFirst then
fargs, pargs = pargs, fargs
end
else
luaArgs = frame
end
-- Set the order of precedence of the argument tables. If the variables are
-- nil, nothing will be added to the table, which is how we avoid clashes
-- between the frame/parent args and the Lua args.
local argTables = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs
--[[
-- Generate the tidyVal function. If it has been specified by the user, we
-- use that; if not, we choose one of four functions depending on the
-- options chosen. This is so that we don't have to call the options table
-- every time the function is called.
--]]
local tidyVal = options.valueFunc
if tidyVal then
if type(tidyVal) ~= 'function' then
error(
"bad value assigned to option 'valueFunc'"
.. '(function expected, got '
.. type(tidyVal)
.. ')',
2
)
end
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end
--[[
-- Set up the args, metaArgs and nilArgs tables. args will be the one
-- accessed from functions, and metaArgs will hold the actual arguments. Nil
-- arguments are memoized in nilArgs, and the metatable connects all of them
-- together.
--]]
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
setmetatable(args, metatable)
local function mergeArgs(tables)
--[[
-- Accepts multiple tables as input and merges their keys and values
-- into one table. If a value is already present it is not overwritten;
-- tables listed earlier have precedence. We are also memoizing nil
-- values, which can be overwritten if they are 's' (soft).
--]]
for _, t in ipairs(tables) do
for key, val in pairs(t) do
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then
local tidiedVal = tidyVal(key, val)
if tidiedVal == nil then
nilArgs[key] = 's'
else
metaArgs[key] = tidiedVal
end
end
end
end
end
--[[
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,
-- and are only fetched from the argument tables once. Fetching arguments
-- from the argument tables is the most resource-intensive step in this
-- module, so we try and avoid it where possible. For this reason, nil
-- arguments are also memoized, in the nilArgs table. Also, we keep a record
-- in the metatable of when pairs and ipairs have been called, so we do not
-- run pairs and ipairs on the argument tables more than once. We also do
-- not run ipairs on fargs and pargs if pairs has already been run, as all
-- the arguments will already have been copied over.
--]]
metatable.__index = function (t, key)
--[[
-- Fetches an argument when the args table is indexed. First we check
-- to see if the value is memoized, and if not we try and fetch it from
-- the argument tables. When we check memoization, we need to check
-- metaArgs before nilArgs, as both can be non-nil at the same time.
-- If the argument is not present in metaArgs, we also check whether
-- pairs has been run yet. If pairs has already been run, we return nil.
-- This is because all the arguments will have already been copied into
-- metaArgs by the mergeArgs function, meaning that any other arguments
-- must be nil.
--]]
if type(key) == 'string' then
key = options.translate[key]
end
local val = metaArgs[key]
if val ~= nil then
return val
elseif metatable.donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs(argTables) do
local argTableVal = tidyVal(key, argTable[key])
if argTableVal ~= nil then
metaArgs[key] = argTableVal
return argTableVal
end
end
nilArgs[key] = 'h'
return nil
end
metatable.__newindex = function (t, key, val)
-- This function is called when a module tries to add a new value to the
-- args table, or tries to change an existing value.
if type(key) == 'string' then
key = options.translate[key]
end
if options.readOnly then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; the table is read-only',
2
)
elseif options.noOverwrite and args[key] ~= nil then
error(
'could not write to argument table key "'
.. tostring(key)
.. '"; overwriting existing arguments is not permitted',
2
)
elseif val == nil then
--[[
-- If the argument is to be overwritten with nil, we need to erase
-- the value in metaArgs, so that __index, __pairs and __ipairs do
-- not use a previous existing value, if present; and we also need
-- to memoize the nil in nilArgs, so that the value isn't looked
-- up in the argument tables if it is accessed again.
--]]
metaArgs[key] = nil
nilArgs[key] = 'h'
else
metaArgs[key] = val
end
end
local function translatenext(invariant)
local k, v = next(invariant.t, invariant.k)
invariant.k = k
if k == nil then
return nil
elseif type(k) ~= 'string' or not options.backtranslate then
return k, v
else
local backtranslate = options.backtranslate[k]
if backtranslate == nil then
-- Skip this one. This is a tail call, so this won't cause stack overflow
return translatenext(invariant)
else
return backtranslate, v
end
end
end
metatable.__pairs = function ()
-- Called when pairs is run on the args table.
if not metatable.donePairs then
mergeArgs(argTables)
metatable.donePairs = true
end
return translatenext, { t = metaArgs }
end
local function inext(t, i)
-- This uses our __index metamethod
local v = t[i + 1]
if v ~= nil then
return i + 1, v
end
end
metatable.__ipairs = function (t)
-- Called when ipairs is run on the args table.
return inext, t, 0
end
return args
end
return arguments
3134ecce8429b810d445e29eae115e2ae4c36c53
Template:Lan
10
31
58
57
2024-08-02T10:37:10Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:lan|main}}</includeonly><noinclude>{{模板文档}}</noinclude>
9a0c6ae29e4b3d5782f1580fbccc37393902b49f
Module:Lan
828
32
60
59
2024-08-02T10:37:11Z
黑茶
2
导入1个版本
Scribunto
text/plain
local l={}
local getArgs
local args
l.fallbackList={
['zh']={'zh','zh-hans','zh-hant','zh-cn','zh-tw','zh-hk','zh-mo','zh-sg','zh-my'}
,['zh-hans']={'zh-hans','zh-cn','zh-sg','zh-my','zh'}
,['zh-hant']={'zh-hant','zh-tw','zh-hk','zh-mo','zh'}
,['zh-cn']={'zh-cn','zh-hans','zh-sg','zh-my','zh'}
,['zh-sg']={'zh-sg','zh-hans','zh-cn','zh-my','zh'}
,['zh-my']={'zh-my','zh-hans','zh-cn','zh-sg','zh'}
,['zh-tw']={'zh-tw','zh-hant','zh-hk','zh-mo','zh'}
,['zh-hk']={'zh-hk','zh-hant','zh-mo','zh-tw','zh'}
,['zh-mo']={'zh-mo','zh-hant','zh-hk','zh-tw','zh'}
}
function l._main(args, frame)
local userlanguage=frame:callParserFunction{ name = 'int', args = {'Conversionname'} }
--mw.message.new('Conversionname'):plain()
local fallback=l.fallbackList[userlanguage]
if fallback == nil then
fallback=l.fallbackList['zh']
end
for _,langArgName in ipairs(fallback) do
if args[langArgName] ~= nil then
return args[langArgName]
end
end
return ''
end
function l.main(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame, {parentFirst=true})
return l._main(args, frame)
end
return l
338e358c23346e2de384e3661a2924949707b3a8
Template:No redirect
10
33
62
61
2024-08-02T10:37:11Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{{{{|safesubst:}}}#if: {{{{{|safesubst:}}}#invoke:Redirect|isRedirect|{{{1}}}}}
| <span class="plainlinks">[{{fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]</span>
| {{{{{|safesubst:}}}#if:{{{2|}}}|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}|{{{2}}}]]|[[:{{{{{|safesubst:}}}FULLPAGENAME:{{{1}}}}}]]}}
}}<noinclude>{{lua|Module:Redirect}}
{{documentation}}
</noinclude>
996c1e73b0906e1e05cab3f9aaff13ea04646ff8
Template:Fullurl
10
34
64
63
2024-08-02T10:37:11Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span class="plainlinks">[{{fullurl:{{{1}}}|{{{2}}}}} {{{3}}}]</span><noinclude>
{{documentation}}</noinclude>
9c51dda6ddd9f9055ed3843b256871781d737593
Module:Redirect
828
35
66
65
2024-08-02T10:37:12Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides functions for getting the target of a redirect page.
local p = {}
-- Gets a mw.title object, using pcall to avoid generating script errors if we
-- are over the expensive function count limit (among other possible causes).
local function getTitle(...)
local success, titleObj = pcall(mw.title.new, ...)
if success then
return titleObj
else
return nil
end
end
-- Gets the name of a page that a redirect leads to, or nil if it isn't a
-- redirect.
function p.getTargetFromText(text, contentModel)
contentModel = contentModel or 'wikitext'
if contentModel == 'wikitext' then
return string.match(
text,
"^%s*#重定向%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#重定向%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)%]%]"
) or string.match(
text,
"^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]"
)
elseif contentModel == 'Scribunto' then
return string.match(
text,
"^%s*return%s+require%s*%[%[([^%[%]|]-)%]%]" -- T120794
) or string.match(
text,
"^%s*return%s+require%s*%(%s*['\"]([^%[%]|]-)['\"]%s*%)"
)
end
return nil
end
-- Gets the target of a redirect. If the page specified is not a redirect,
-- returns nil.
function p.getTarget(page, fulltext)
-- Get the title object. Both page names and title objects are allowed
-- as input.
local titleObj
if type(page) == 'string' or type(page) == 'number' then
titleObj = getTitle(page)
elseif type(page) == 'table' and type(page.getContent) == 'function' then
titleObj = page
else
error(string.format(
"错误参数 #1,调用 'getTarget'"
.. " (需要字符串,数字,或标题对象;得到%s)",
type(page)
), 2)
end
if not titleObj or not titleObj.isRedirect then
return nil
end
-- Find the target by using string matching on the page content.
local target = p.getTargetFromText(titleObj:getContent() or "", titleObj.contentModel)
--優先使用原本的判斷方式,如果判斷不出來,再直接用redirectTarget
or titleObj.redirectTarget
if target then
local targetTitle = getTitle(target)
if targetTitle then
if fulltext then
return targetTitle.fullText
else
return targetTitle.prefixedText
end
else
return nil
end
else
-- The page is a redirect, but matching failed. This indicates a bug in
-- the redirect matching pattern, so throw an error.
error(string.format(
'无法处理页面"%s"上的重定向',
fulltext and titleObj.fullText or titleObj.prefixedText
))
end
end
--[[
-- Given a single page name determines what page it redirects to and returns the
-- target page name, or the passed page name when not a redirect. The passed
-- page name can be given as plain text or as a page link.
--
-- Returns page name as plain text, or when the bracket parameter is given, as a
-- page link. Returns an error message when page does not exist or the redirect
-- target cannot be determined for some reason.
--]]
function p.luaMain(rname, bracket, fulltext)
if type(rname) ~= "string" or not rname:find("%S") then
return nil
end
bracket = bracket and "[[%s]]" or "%s"
rname = rname:match("%[%[(.+)%]%]") or rname
local target = p.getTarget(rname, fulltext)
local ret = target or rname
ret = getTitle(ret)
if ret then
if fulltext then
ret = ret.fullText
else
ret = ret.prefixedText
end
return bracket:format(ret)
else
return nil
end
end
-- Provides access to the luaMain function from wikitext.
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
return p.luaMain(args[1], args.bracket, args.fulltext) or ''
end
-- Returns true if the specified page is a redirect, and false otherwise.
function p.luaIsRedirect(page)
local titleObj = getTitle(page)
if not titleObj then
return false
end
if titleObj.isRedirect then
return true
else
return false
end
end
-- Provides access to the luaIsRedirect function from wikitext, returning 'yes'
-- if the specified page is a redirect, and the blank string otherwise.
function p.isRedirect(frame)
local args = require('Module:Arguments').getArgs(frame, {frameOnly = true})
if p.luaIsRedirect(args[1]) then
return 'yes'
else
return ''
end
end
return p
33015ebf3343aa4b100d4568e0d1fd69e0408235
Template:If mobile
10
36
68
67
2024-08-02T10:37:12Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:If mobile|main}}<noinclude>
{{Documentation}}</noinclude>
704e8b891b9980b01d12ed061de7486c87b2274b
Template:If mobile/styles.css
10
37
70
69
2024-08-02T10:37:12Z
黑茶
2
导入1个版本
sanitized-css
text/css
/* Because of how TemplateStyles and MobileFrontend work, it's not possible to
directly test for whether the mobile site is being used in a TemplateStyle. As
such we'll use Minerva as a proxy. This is imperfect. */
body:not(.skin-minerva) .ifmobile > .mobile {
display: none;
}
/*
Force nomobile element to display when present.
Overrides skin-based css for hiding the nomobile class, e.g. Timeless skin with screen size less than 850px.
*/
body.skin-minerva .ifmobile > .nomobile {
display: inherit; /* The fallback */
display: initial;
}
64e9502c6c99627f7760022c2c8ecd83e3699f4a
Template:Div col
10
38
72
71
2024-08-02T10:37:13Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><templatestyles src="Div col/styles.css"/><!--
--><div class="div-col {{#ifeq:{{{small|}}}|yes|div-col-small}} {{#ifeq:{{{rules|}}}|yes|div-col-rules}} {{{class|}}}" <!--
-->{{#if:{{{cols|{{{1|}}}}}}{{{colwidth|{{{2|}}}}}}{{{gap|}}}{{{style|}}}|<!--
-->style="{{#if:{{{cols|{{{1|}}}}}}|column-count:{{{cols|{{{1|}}}}}}; column-width:auto;<!-- 用以覆盖[[T:Div col/styles.css]]中预设的列宽“30em”,使列数不受其影响 -->}}{{#if:{{{colwidth|{{{2|}}}}}}|column-width:{{{colwidth|{{{2|}}}}}};}}{{#if:{{{gap|}}}|column-gap:{{{gap}}};}}{{#if:{{{style|}}}|{{{style}}}}}"<!--
-->}}><!--
-->{{#if:{{{content|}}}|{{{content}}}</div>}}<!-- Inventory how many pages use small=yes
--><!--{{#ifeq:{{{small|}}}|yes|[[Category:Pages using div col with small parameter]]}}--><!--
--></includeonly><!--{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter "_VALUE_"; use colwidth= to specify column size |ignoreblank=y | class | colwidth | content | gap | rules | small | style }}--><noinclude>
{{Documentation}}
</noinclude>
b9f1dd532f74d3c57839cafc7017868d579f8880
Template:Div col/styles.css
10
39
74
73
2024-08-02T10:37:13Z
黑茶
2
导入1个版本
sanitized-css
text/css
/* {{pp|small=yes}} */
.div-col {
margin-top: 0.3em;
column-width: 30em;
}
.div-col-small {
font-size: 90%;
}
.div-col-rules {
column-rule: 1px solid #aaa;
}
/* Reset top margin for lists in div col */
.div-col dl,
.div-col ol,
.div-col ul {
margin-top: 0;
}
/* Avoid elements breaking between columns
See also Template:No col break */
.div-col li,
.div-col dd {
page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */
break-inside: avoid-column;
}
/* Unbulleted lists */
.plainlist ol,
.plainlist ul {
line-height: inherit;
list-style: none;
margin: 0;
}
.plainlist ol li,
.plainlist ul li {
margin-bottom: 0;
}
76c2c0a042b9164cff638cd44af5ab129702c141
Template:Div col end
10
40
76
75
2024-08-02T10:37:14Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly></div></includeonly><noinclude>
{{Documentation|Template:Div col/doc}}
</noinclude>
78088d41c21d779e3722f220fcc9773dfbbc1e4f
Template:Fullurl2
10
41
78
77
2024-08-02T10:37:14Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{{{{|safesubst:}}}#invoke:fullurl|fullurl}}<noinclude>
{{doc}}</noinclude>
bcec16f0cb14ffd7fbc29d4efa40670958541c85
Module:Fullurl
828
42
80
79
2024-08-02T10:37:14Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
local yesno = require('Module:Yesno')
local mError = require('Module:Error').error
function p._fullurl(args)
local paid = ''
local title = args['title'] or args[1] or args['1'] or tostring(mw.title.getCurrentTitle())
if title == '' then
--不能讓title變空值,否則url會返回nil
title = tostring(mw.title.getCurrentTitle())
end
local text = args['text'] or args[2] or args['1'] or title
for k, v in pairs( args ) do
if ((k == 'title') or (k == 1) or (k == '1') or (k == 'text') or (k == 2) or (k == '2') or (k == 'onlyurl') or (k == 'paid')) then
if (k == 'paid') then
if paid == '' then
paid = mw.text.trim(v)
else
paid = paid .. '&' .. mw.text.trim(v)
end
end
else
if paid == '' then
paid = k .. '=' .. mw.text.trim(v)
else
paid = paid .. '&' .. k .. '=' .. mw.text.trim(v)
end
end
end
local url = tostring(mw.uri.fullUrl(title,paid))
local plainlink = '<span class="plainlinks">[' .. url .. ' ' .. text .. ']</span>'
if (args['action'] == 'submit') then
return plainlink .. mError{'[[Module:Fullur]]錯誤:<code>|action=submin</code>不是有效的值,請使用<code>|action=edit</code>。'}
else
if yesno(args['onlyurl']) then
return url
else
return plainlink
end
end
end
function p.fullurl(frame)
local args = {}
for k, v in pairs( frame.args ) do
args[k] = v
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
return p._fullurl(args)
end
function p._fullurl2(title ,paid, text)
return '<span class="plainlinks">[' .. tostring(mw.uri.fullUrl(title,paid)) .. ' ' .. text .. ']</span>'
end
--[=[
function p.hosturl ()
return "//zh.wikipedia.org"
end
function p.scripturl ()
return p.hosturl () .. "/w"
end
function p.index ()
return p.scripturl () .. "/index.php"
end
function p.articlepath ()
return p () .. "/wiki"
end
p["index.php"] = function ()
return p.index ()
end
p["api.php"] = function ()
return p.scripturl () .. "/api.php"
end
p["rest.php"] = function (frame)
return p.scripturl () .. "/rest.php"
end
]=]--
return p
a16d8a94b2b7a8090d4736d5e0b986cce97ff318
Template:Void
10
43
82
81
2024-08-02T10:37:14Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{doc}}</noinclude>
2ad0a7aac7bb5b51850ca5d508fcde851272e224
Template:Shortcut
10
45
84
83
2024-08-02T10:37:15Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Shortcut|main}}</includeonly><noinclude>{{Documentation}}</noinclude>
366b7fa8a7ebad556d8ab80288b32d97172cef80
Template:Shortcut/styles.css
10
46
86
85
2024-08-02T10:37:15Z
黑茶
2
导入1个版本
sanitized-css
text/css
.shortcutbox {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.shortcutbox-left {
float:left;
}
.shortcutbox-ombox {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.shortcut-anchordiv {
position:relative;
top:-3em;
}
.module-shortcutboxplain {
float:right;
border:1px solid #aaa;
background-color: var(--background-color-base,#fff);
margin:0 0 0 1em;
padding:.3em .6em .2em .6em;
text-align:center;
font-size:85%;
font-weight:bold;
white-space: nowrap;
}
.module-shortcutboxplain-left {
float:left;
}
.module-omboxshortcutplain {
float: right;
border-left: 1px solid #aaa;
padding: .4em 0em .4em 1em;
text-align: center;
line-height: 1.4em;
font-weight: bold;
font-size: smaller;
white-space: nowrap;
}
.module-shortcutlist {
display:inline-block;
border-bottom:1px solid #aaa;
margin-bottom:.2em;
font-weight: normal;
}
.module-shortcutanchordiv {
position:relative;
top:-3em;
}
9c4ef4c581a945084d5e44c5b35135cef5ea8c27
Module:Shortcut
828
47
88
87
2024-08-02T10:37:15Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{shortcut}}.
-- Set constants
local CONFIG_MODULE = 'Module:Shortcut/config'
-- Load required modules
local checkType = require('libraryUtil').checkType
local yesno = require('Module:Yesno')
local p = {}
function p._getshortname(frame)
return frame:expandTemplate{title = "Lan",args = {["zh-hans"]="快捷方式",["zh-hant"]="捷徑"}}
end
function p.getshortlink(frame)
return "[[Wikipedia:捷徑|" .. p._getshortname(frame) .. "]]"
end
function p.getshortlink_policy(frame)
return "[[Wikipedia:捷徑|方針" .. p._getshortname(frame) .. "]]"
end
local function message(msg, ...)
return mw.message.newRawMessage(msg, ...):plain()
end
local function makeCategoryLink(cat)
return string.format('[[%s:%s]]', mw.site.namespaces[14].name, cat)
end
function p._main(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = {shortcut}
}
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
if yesno(options.policy) then
shortcutHeading = p.getshortlink_policy(frame)
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain plainlist noprint')
:attr('role', 'note')
if options.float == 'left' then
shortcutList:addClass('module-shortcutboxplain-left')
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._main(shortcuts, options, frame)
end
function p._ombx(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = frame:expandTemplate{
title = 'No redirect',
args = {shortcut}
}
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-omboxshortcutplain plainlist noprint')
:attr('role', 'note')
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.ombox(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._ombx(shortcuts, options, frame)
end
function p._template(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = '{{'
.. frame:expandTemplate{
title = 'Template_shortcut/link',
args = {shortcut}
}..'}}'
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', 'Template:'..anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(cfg['shortcut-heading'], nShortcuts)
shortcutHeading = shortcutHeading
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-shortcutboxplain plainlist noprint')
:attr('role', 'note')
if options.float == 'left' then
shortcutList:addClass('module-shortcutboxplain-left')
end
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.template(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._template(shortcuts, options, frame)
end
function p._ombx_template(shortcuts, options, frame, cfg)
checkType('_main', 1, shortcuts, 'table')
checkType('_main', 2, options, 'table', true)
options = options or {}
frame = frame or mw.getCurrentFrame()
cfg = cfg or mw.loadData(CONFIG_MODULE)
local isCategorized = yesno(options.category) ~= false
-- Validate shortcuts
for i, shortcut in ipairs(shortcuts) do
if type(shortcut) ~= 'string' or #shortcut < 1 then
error(message(cfg['invalid-shortcut-error'], i), 2)
end
end
-- Make the list items. These are the shortcuts plus any extra lines such
-- as options.msg.
local listItems = {}
for i, shortcut in ipairs(shortcuts) do
listItems[i] = '{{'
.. frame:expandTemplate{
title = 'Template_shortcut/link',
args = {shortcut}
}..'}}'
end
table.insert(listItems, options.msg)
-- Return an error if we have nothing to display
if #listItems < 1 then
local msg = cfg['no-content-error']
msg = string.format('<strong class="error">%s</strong>', msg)
if isCategorized and cfg['no-content-error-category'] then
msg = msg .. makeCategoryLink(cfg['no-content-error-category'])
end
return msg
end
local root = mw.html.create()
root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Shortcut/styles.css'} })
-- Anchors
local anchorDiv = root
:tag('div')
:addClass('module-shortcutanchordiv')
for i, shortcut in ipairs(shortcuts) do
local anchor = mw.uri.anchorEncode(shortcut)
anchorDiv:tag('span'):attr('id', 'Template:'..anchor)
end
-- Shortcut heading
local shortcutHeading
do
local nShortcuts = #shortcuts
if nShortcuts > 0 then
shortcutHeading = message(p.getshortlink(frame), nShortcuts)
shortcutHeading = frame:preprocess(shortcutHeading)
end
end
-- Shortcut box
local shortcutList = root
:tag('div')
:addClass('module-omboxshortcutplain plainlist noprint')
:attr('role', 'note')
if shortcutHeading then
shortcutList
:tag('div')
:addClass('module-shortcutlist')
:wikitext(shortcutHeading)
end
local list = shortcutList:tag('ul')
for i, item in ipairs(listItems) do
list:tag('li'):wikitext(item)
end
return tostring(root)
end
function p.ombox_template(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Shortcut'
})
-- Separate shortcuts from options
local shortcuts, options = {}, {}
for k, v in pairs(args) do
if type(k) == 'number' then
shortcuts[k] = v
else
options[k] = v
end
end
-- Compress the shortcut array, which may contain nils.
local function compressArray(t)
local nums, ret = {}, {}
for k in pairs(t) do
nums[#nums + 1] = k
end
table.sort(nums)
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end
shortcuts = compressArray(shortcuts)
return p._ombx_template(shortcuts, options, frame)
end
return p
35e3570422190b34fe2fc94ccd9380657b0b5165
Module:Shortcut/config
828
48
90
89
2024-08-02T10:37:16Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module holds configuration data for [[Module:Shortcut]].
return {
-- The heading at the top of the shortcut box. It accepts the following parameter:
-- $1 - the total number of shortcuts. (required)
['shortcut-heading'] = '[[Wikipedia:捷徑|-{zh-hans:快捷方式;zh-hant:捷徑}-]]',
-- The error message to display when a shortcut is invalid (is not a string, or
-- is the blank string). It accepts the following parameter:
-- $1 - the number of the shortcut in the argument list. (required)
['invalid-shortcut-error'] = '捷徑「#$1」無效(捷徑必須為' ..
'字串且長度至少為1個字元)[[Category:需要修正維基百科捷徑框參數的頁面|{{PAGENAME}}]]',
-- The error message to display when no shortcuts or other displayable content
-- were specified. (required)
['no-content-error'] = '錯誤:沒有指定捷徑名稱並且參數<code>msg</code>沒有定義。[[Category:需要修正維基百科捷徑框參數的頁面|{{PAGENAME}}]]',
-- A category to add when the no-content-error message is displayed. (optional)
--[[
我們並沒有個分類
['no-content-error-category'] = 'Shortcut模板中缺乏參數',
]]--
}
4ceb810cfde3ea15230441bf7f30de4ed0177b2c
Template:請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。
10
49
92
91
2024-08-02T10:37:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Sandbox heading]]
623db2a6ae7dc15c833cef604ced75a5c2e01189
Template:Sandbox heading
10
50
94
93
2024-08-02T10:37:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<!--
简体中文
注意:这不是一个沙盒!!!
这是一个放置于沙盒顶端的模板。
如果你想练习编辑,请不要在这个模板上进行。
你可以通过在搜索中输入“WP:S”或“WP:Temp”或“WP:SB”或“Wikipedia:沙盒”找到真正的沙盒
如果你想在模板空间测试,请前往 “Template:沙盒” 或 “Template:X1” 和 “Template:X2”
再次申明,这个模版不是用于试验的!
这个沙盒模版位于:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><!--
繁體中文
注意:這不是一個沙盒!!!
這是一個放置於沙盒頂端的模板。
如果你想練習編輯,請不要在這個模板上進行。
你可以透過在搜尋中輸入「WP:Temp」或「WP:SB」或「Wikipedia:沙盒」找到真正的沙盒
如果你想在模板空間測試,請前往「WP:S」或「Template:沙盒」或「Template:X1」和「Template:X2」
再次申明,這個模板不是用於試驗的!
這個沙盒模板位於:https://zh.wikipedia.org/wiki/Template:Sandbox_heading
--><noinclude>{{About|置于沙盒顶端的提示-{zh-hant:資訊; zh-hans:信息;}-。'''本模板本身不是沙盒'''|用于测试的模板沙盒|模板:沙盒}}{{nottest}}</noinclude><includeonly>__NOINDEX__</includeonly>
{{noEdit}}
<!-- 不应修改沙盒的首段 - 首段包含对此模板的引用 -->
<div class="messagebox plainlinks" style="padding: 10px; margin: 20px auto; width: 100%; font-size: 10pt;background-color:var(--background-color-interactive-subtle,#f8f9fa);color: inherit;">
{|
|-
||[[File:Edit_In_Sandbox_Icon_-_Color.svg|75px|left|alt=|link=]]
||<big>欢迎来到'''[[Wikipedia:关于沙盒|维基百科沙盒]]'''!</big>
{{{editnotice|
如果{{lan|zh-hans=您|zh-hant=您|zh-hk=閣下}}想要在此測試,請{{Fullurl|1={{FULLPAGENAME}}|2=action=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}或上方的{{If mobile|'''鉛筆{{lan|zh-hans=图标|zh-hant=圖示}}'''|{{#if:{{{1|}}}||'''編輯{{lan|zh-cn=源代码|zh-sg=原始码|zh-tw=原始碼}}'''}}}}即可,也可{{Fullurl|1={{FULLPAGENAME}}|2=veaction=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}使用[[WP:VE|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]]進行編輯。}}}
沙盒是用于练习页面编辑技巧的測試页面。您可在此随意地进行编辑的练习。完成编辑后,可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Showpreview}}'''”按钮预览内容,也可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Publishchanges}}'''”按钮{{lan|zh-cn=保存|zh-tw=儲存}}内容。就像在沙灘上所寫的文字涨潮时就會消失,同样沙盒中所寫的內容,隨時可能被清空,不會有任何預先通知(但曾{{lan|zh-cn=保存|zh-tw=儲存}}的内容仍会永久存留在页面的历史记录中)。
||
{{#switch: {{FULLPAGENAME}}
| Wikipedia:沙盒 = {{Shortcut|WP:S|WP:SB|WP:SAND|WP:TMP|WP:TEST|WP:FOO}}<!--
| Template:沙盒 = {{Shortcut|T:SB}} -->
| Template:X1 = {{Shortcut|T:X1}}
| Template:X2 = {{Shortcut|T:X2}}
| Template:X3 = {{Shortcut|T:X3}}
| Category:沙盒 = {{Shortcut|CAT:SB}}
| 模块:沙盒 = {{Shortcut|Module:SB}}
| Draft:沙盒 = {{Shortcut|Draft:SB}}
| Template:沙盒/test.css = {{Shortcut|T:SB/CSS}}
}}
|}
{{columns|bgcol=transparent;width:100%|width=50%
|col1 = '''注意事项''':
* '''不要'''在公用的沙盒撰写条目或存放其他有价值的内容(請参考[[Help:创建新条目|{{lan|zh-cn=创建|zh-tw=建立}}新页面]]及[[WP:WIZ|{{lan|zh-cn=创建|zh-tw=建立}}条目向导]]);
* '''不要'''在沙盒{{lan|zh-cn=里|zh-hk=裏|zh-tw=裡}}{{lan|zh-cn=保存|zh-tw=儲存}}有侵犯他人版权、攻击性、诽谤中伤他人或他人隱私的内容;
* '''不要'''将沙盒[[Wikipedia:重定向|{{lan|zh-cn=重定向|zh-tw=重新導向}}]]至别的页面,或将顶部模板移除;
* '''不要'''在沙盒進行廣告宣傳或刷编辑次数,否則可能會被[[Wikipedia:封禁方针|{{lan|zh-hans=封禁|zh-hant=封鎖}}]];
* 歡迎參考[[Wikipedia:常见问题解答|常見問題解答]]及[[Wikipedia:新手入門/主頁|使用指南]];
* 如果对[[维基百科]]有任何问题,請到[[Wikipedia:互助客栈|互助客栈]]询问。
|col2 = '''工具''':
{{div col|cols=2}}
* [[Wikipedia:沙盒|主沙盒]]
** {{fullurl2|Wikipedia:沙盒|action=edit|原始碼編輯}}
** {{fullurl2|Wikipedia:沙盒|veaction=edit|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯}}
* {{noredirect|Wikipedia:重定向沙盒|{{lan|zh-cn=重定向|zh-tw=重新導向}}沙盒}}
* [[User:沙盒页|{{lan|zh-cn=用户页|zh-tw=使用者頁面}}沙盒]]
* [[Template:沙盒|模板測試沙盒]]([[Template:X1|X1]]、[[Template:X2|X2]]、[[Template:X3|X3]]、[[Template:沙盒/TemplateStyles|TS]])
* [[Template:沙盒/TemplateStyles|模板樣式總測試沙盒]]
* [[:Category:沙盒|分類測試沙盒]]
* 圖片測試沙盒:[[:File:沙盒.png|PNG]]、[[:File:沙盒.svg|SVG]]
* [[User talk:Sandbox for user warnings~zhwiki|对话页測試沙盒]]([[User talk:Sandbox for user warnings~zhwiki~Flow|Flow版]])
* [[Module:沙盒|{{lan|zh-hans=模块|zh-hant=模組}}總測試沙盒]]
* [[Wikipedia talk:Flow tests|Flow對話沙盒]]
* [{{fullurl:Draft:沙盒|veaction=edit}} {{lan|zh-hans=可视化|zh-hant=視覺化}}编辑器沙盒]
* [[WP:Huggle/Sandbox|Huggle沙盒]]
* [[Special:ApiSandbox|API沙盒]]
* 維基數據沙盒:[[:d:Q4115189|1]]、[[:d:Q13406268|2]]、[[:d:Q15397819|3]]、[[:d:Q112795079|4]]
* [[testwiki:|測試維基]]
* [[mw:Project:Sandbox|MediaWiki沙盒]]([[mw:VisualEditor:Test|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]])
* [{{fullurl:Special:Mypage/沙盒|action=edit&preload=Template:用戶沙盒/preload}} 您自己的沙盒]
* [[Wikipedia:關於沙盒|其他{{lan|zh-hans=资料|zh-hant=資料}}]]
{{div col end}}
}}
</div><div class="abusefilter-sandbox-header"></div><includeonly>
{{#switch:{{FULLPAGENAME}}
| Category:沙盒 = {{hiddencat}}
[[Category:維基百科管理]]
| #default = {{#ifeq:{{NAMESPACE}}|User||{{#ifeq:{{NAMESPACE}}|User talk||{{#if:{{{8|}}}||[[Category:沙盒]]}}}}}}
}}</includeonly>
{{{editnotice|
----}}}<noinclude>
{{doc}}
</noinclude>
f2ad992b81199261b0c806fb320939944a642b1a
107
94
2024-08-02T10:46:28Z
黑茶
2
替换从维基百科导入的模板的一些字段
wikitext
text/x-wiki
<!--
简体中文
注意:这不是一个沙盒!!!
这是一个放置于沙盒顶端的模板。
如果你想练习编辑,请不要在这个模板上进行。
你可以通过在搜索中输入“WP:S”或“WP:Temp”或“WP:SB”或“那艺娜维基:沙盒”找到真正的沙盒
如果你想在模板空间测试,请前往 “Template:沙盒” 或 “Template:X1” 和 “Template:X2”
再次申明,这个模版不是用于试验的!
这个沙盒模版位于:https://ladynana.miraheze.org/wiki/Template:Sandbox_heading
--><!--
繁體中文
注意:這不是一個沙盒!!!
這是一個放置於沙盒頂端的模板。
如果你想練習編輯,請不要在這個模板上進行。
你可以透過在搜尋中輸入「WP:Temp」或「WP:SB」或「那艺娜维基:沙盒」找到真正的沙盒
如果你想在模板空間測試,請前往「WP:S」或「Template:沙盒」或「Template:X1」和「Template:X2」
再次申明,這個模板不是用於試驗的!
這個沙盒模板位於:https://ladynana.miraheze.org/wiki/Template:Sandbox_heading
--><noinclude>{{About|置于沙盒顶端的提示-{zh-hant:資訊; zh-hans:信息;}-。'''本模板本身不是沙盒'''|用于测试的模板沙盒|模板:沙盒}}{{nottest}}</noinclude><includeonly>__NOINDEX__</includeonly>
{{noEdit}}
<!-- 不应修改沙盒的首段 - 首段包含对此模板的引用 -->
<div class="messagebox plainlinks" style="padding: 10px; margin: 20px auto; width: 100%; font-size: 10pt;background-color:var(--background-color-interactive-subtle,#f8f9fa);color: inherit;">
{|
|-
||[[File:Edit_In_Sandbox_Icon_-_Color.svg|75px|left|alt=|link=]]
||<big>欢迎来到'''[[那艺娜维基:关于沙盒|那艺娜维基沙盒]]'''!</big>
{{{editnotice|
如果{{lan|zh-hans=您|zh-hant=您|zh-hk=閣下}}想要在此測試,請{{Fullurl|1={{FULLPAGENAME}}|2=action=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}或上方的{{If mobile|'''鉛筆{{lan|zh-hans=图标|zh-hant=圖示}}'''|{{#if:{{{1|}}}||'''編輯{{lan|zh-cn=源代码|zh-sg=原始码|zh-tw=原始碼}}'''}}}}即可,也可{{Fullurl|1={{FULLPAGENAME}}|2=veaction=edit|3='''{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}此處'''}}使用[[WP:VE|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]]進行編輯。}}}
沙盒是用于练习页面编辑技巧的測試页面。您可在此随意地进行编辑的练习。完成编辑后,可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Showpreview}}'''”按钮预览内容,也可{{lan|zh-cn=点击|zh-hk=點擊|zh-tw=點選}}“'''{{int:Publishchanges}}'''”按钮{{lan|zh-cn=保存|zh-tw=儲存}}内容。就像在沙灘上所寫的文字涨潮时就會消失,同样沙盒中所寫的內容,隨時可能被清空,不會有任何預先通知(但曾{{lan|zh-cn=保存|zh-tw=儲存}}的内容仍会永久存留在页面的历史记录中)。
||
{{#switch: {{FULLPAGENAME}}
| 那艺娜维基:沙盒 = {{Shortcut|WP:S|WP:SB|WP:SAND|WP:TMP|WP:TEST|WP:FOO}}<!--
| Template:沙盒 = {{Shortcut|T:SB}} -->
| Template:X1 = {{Shortcut|T:X1}}
| Template:X2 = {{Shortcut|T:X2}}
| Template:X3 = {{Shortcut|T:X3}}
| Category:沙盒 = {{Shortcut|CAT:SB}}
| 模块:沙盒 = {{Shortcut|Module:SB}}
| Draft:沙盒 = {{Shortcut|Draft:SB}}
| Template:沙盒/test.css = {{Shortcut|T:SB/CSS}}
}}
|}
{{columns|bgcol=transparent;width:100%|width=50%
|col1 = '''注意事项''':
* '''不要'''在公用的沙盒撰写条目或存放其他有价值的内容(請参考[[Help:创建新条目|{{lan|zh-cn=创建|zh-tw=建立}}新页面]]及[[WP:WIZ|{{lan|zh-cn=创建|zh-tw=建立}}条目向导]]);
* '''不要'''在沙盒{{lan|zh-cn=里|zh-hk=裏|zh-tw=裡}}{{lan|zh-cn=保存|zh-tw=儲存}}有侵犯他人版权、攻击性、诽谤中伤他人或他人隱私的内容;
* '''不要'''将沙盒[[那艺娜维基:重定向|{{lan|zh-cn=重定向|zh-tw=重新導向}}]]至别的页面,或将顶部模板移除;
* '''不要'''在沙盒進行廣告宣傳或刷编辑次数,否則可能會被[[那艺娜维基:封禁方针|{{lan|zh-hans=封禁|zh-hant=封鎖}}]];
* 歡迎參考[[那艺娜维基:常见问题解答|常見問題解答]]及[[那艺娜维基:新手入門/主頁|使用指南]];
* 如果对[[那艺娜维基]]有任何问题,請到[[那艺娜维基:互助客栈|互助客栈]]询问。
|col2 = '''工具''':
{{div col|cols=2}}
* [[那艺娜维基:沙盒|主沙盒]]
** {{fullurl2|那艺娜维基:沙盒|action=edit|原始碼編輯}}
** {{fullurl2|那艺娜维基:沙盒|veaction=edit|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯}}
* {{noredirect|那艺娜维基:重定向沙盒|{{lan|zh-cn=重定向|zh-tw=重新導向}}沙盒}}
* [[User:沙盒页|{{lan|zh-cn=用户页|zh-tw=使用者頁面}}沙盒]]
* [[Template:沙盒|模板測試沙盒]]([[Template:X1|X1]]、[[Template:X2|X2]]、[[Template:X3|X3]]、[[Template:沙盒/TemplateStyles|TS]])
* [[Template:沙盒/TemplateStyles|模板樣式總測試沙盒]]
* [[:Category:沙盒|分類測試沙盒]]
* 圖片測試沙盒:[[:File:沙盒.png|PNG]]、[[:File:沙盒.svg|SVG]]
* [[User talk:Sandbox for user warnings~zhwiki|对话页測試沙盒]]([[User talk:Sandbox for user warnings~zhwiki~Flow|Flow版]])
* [[Module:沙盒|{{lan|zh-hans=模块|zh-hant=模組}}總測試沙盒]]
* [[Wikipedia talk:Flow tests|Flow對話沙盒]]
* [{{fullurl:Draft:沙盒|veaction=edit}} {{lan|zh-hans=可视化|zh-hant=視覺化}}编辑器沙盒]
* [[WP:Huggle/Sandbox|Huggle沙盒]]
* [[Special:ApiSandbox|API沙盒]]
* 維基數據沙盒:[[:d:Q4115189|1]]、[[:d:Q13406268|2]]、[[:d:Q15397819|3]]、[[:d:Q112795079|4]]
* [[testwiki:|測試維基]]
* [[mw:Project:Sandbox|MediaWiki沙盒]]([[mw:VisualEditor:Test|{{lan|zh-hans=可视化|zh-hant=視覺化}}編輯器]])
* [{{fullurl:Special:Mypage/沙盒|action=edit&preload=Template:用戶沙盒/preload}} 您自己的沙盒]
* [[那艺娜维基:關於沙盒|其他{{lan|zh-hans=资料|zh-hant=資料}}]]
{{div col end}}
}}
</div><div class="abusefilter-sandbox-header"></div><includeonly>
{{#switch:{{FULLPAGENAME}}
| Category:沙盒 = {{hiddencat}}
[[Category:那艺娜维基管理]]
| #default = {{#ifeq:{{NAMESPACE}}|User||{{#ifeq:{{NAMESPACE}}|User talk||{{#if:{{{8|}}}||[[Category:沙盒]]}}}}}}
}}</includeonly>
{{{editnotice|
----}}}<noinclude>
{{doc}}
</noinclude>
69da9387edc58ceca30f905af6221a14460bc9b7
Template:NoEdit
10
51
96
95
2024-08-02T10:37:17Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#if:{{{|}}}<!--
产生没有编辑按钮的标题 -->|<div class="noedit">
={{{|}}}
</div><!--
编辑首段按钮不出现 -->|<span id="no-edit-0"></span><!--
结束 -->}}</includeonly><noinclude>
{{模板文档}}
</noinclude>
2908b829aa6bf620e236da30d2e5c6bc6c5b57d4
Template:Columns
10
52
98
97
2024-08-02T10:37:17Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<templatestyles src="Columns/styles.css" /><table class="multicol skin-nightmode-reset-color" style="{{#switch:{{{align|}}}
|left|right=float:{{{align}}}
|center=margin:0.5em auto
}};border-spacing:0;background:{{{background|{{{bgcol|transparent}}}}}};{{#if:{{{text-align|}}}|text-align:{{{text-align}}};}}{{{style|}}}" role="presentation">
<tr style="vertical-align:top;">
<td style="width:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col1style|}}};">{{#ifeq:{{{col1width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col1}}}</td>
{{#if:{{{col2<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col2style|}}};">{{#ifeq:{{{col2width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col2}}}</td>
}}{{#if:{{{col3<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col3style|}}};">{{#ifeq:{{{col3width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col3}}}</td>
}}{{#if:{{{col4<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col4style|}}};">{{#ifeq:{{{col4width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col4}}}</td>
}}{{#if:{{{col5<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col5style|}}};">{{#ifeq:{{{col5width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col5}}}</td>
}}{{#if:{{{col6<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col6style|}}};">{{#ifeq:{{{col6width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col6}}}</td>
}}{{#if:{{{col7<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col7style|}}};">{{#ifeq:{{{col7width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col7}}}</td>
}}{{#if:{{{col8<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col8style|}}};">{{#ifeq:{{{col8width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col8}}}</td>
}}{{#if:{{{col9<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col9style|}}};">{{#ifeq:{{{col9width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col9}}}</td>
}}{{#if:{{{col10<includeonly>|</includeonly>}}}
| <td style="width:{{{gapbetween|{{{gap|1.25em}}}}}};"></td>
<td style="width:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}};{{{colstyle|}}};{{{col10style|}}};">{{#ifeq:{{{col10width|{{{colwidth|{{{width|15.0em}}}}}}}}}|15.0em|[[Category:多栏位表格]]}}
{{{col10}}}</td>
}}
</tr></table><noinclude>{{Documentation}}</noinclude>
3c43118d7fdd34f4c2eeb0eb1de02303f4435f19
Template:Columns/styles.css
10
53
100
99
2024-08-02T10:37:18Z
黑茶
2
导入1个版本
sanitized-css
text/css
@media (min-width: 720px) {
.columns-start .column {
/* @noflip */
float: left;
min-width: 20em;
}
.columns-2 .column {
width: 50%;
}
.columns-3 .column {
width: 33.3%;
}
.columns-4 .column {
width: 25%;
}
.columns-5 .column {
width: 20%;
}
}
da82fb4f7604181dee3116fd03863f7fb2beb7ea
Template:请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。
10
54
102
101
2024-08-02T10:37:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Void]]
90ff2dc1111160c936f3a960d5c2158a7628aed5
Template:Noredirect
10
55
104
103
2024-08-02T10:37:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:No redirect]]
7bbca779757c40530991fa4afadd831104b1287e
Module:If mobile
828
56
106
105
2024-08-02T10:37:19Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p._main(args)
local frame = mw.getCurrentFrame()
local root = mw.html.create()
if args["Tag"] then
args["tag"] = args["Tag"]
end
local ifmobile = root:tag(args["tag"] or 'span')
ifmobile
:addClass('ifmobile')
local nomobile = ifmobile:tag(args["tag"] or 'span')
local mobile = ifmobile:tag(args["tag"] or 'span')
nomobile
:addClass('nomobile')
:wikitext(args[2])
mobile
:addClass('mobile')
:wikitext(args[1])
return frame:extensionTag {name = 'templatestyles', args = {src = 'If mobile/styles.css'}} .. tostring(root)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:If mobile'
})
return p._main(args)
end
return p
0dc3a7be7f6c018c054779b0c4b4cc1f43380752
Template:About
10
57
109
108
2024-08-02T10:51:15Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:about|about}}</includeonly><noinclude>{{Documentation}}</noinclude>
f33ff16000b289ea53090134dcae2e291c87c043
Template:Nottest
10
58
111
110
2024-08-02T10:51:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Not a sandbox]]
2bb1a24d63bd44c5065444f91a511008c03ce2a3
Module:Message box
828
59
113
112
2024-08-02T10:51:16Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This is a meta-module for producing message box templates, including {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.
-- Require necessary modules.
local getArgs = require('Module:Arguments').getArgs
local categoryHandler = require('Module:Category handler').main
local yesno = require('Module:Yesno')
-- Load the configuration page.
local cfgTables = mw.loadData('Module:Message box/configuration')
-- Get a language object for formatDate and ucfirst.
local lang = mw.language.getContentLanguage()
-- Set aliases for often-used functions to reduce table lookups.
local format = mw.ustring.format
local tinsert = table.insert
local tconcat = table.concat
local trim = mw.text.trim
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitleObject(page, ...)
if type(page) == 'string' then
-- Get the title object, passing the function through pcall
-- in case we are over the expensive function count limit.
local success, title = pcall(mw.title.new, page, ...)
if success then
return title
end
end
end
local function union(t1, t2)
-- Returns the union of two arrays.
local vals = {}
for i, v in ipairs(t1) do
vals[v] = true
end
for i, v in ipairs(t2) do
vals[v] = true
end
local ret = {}
for k in pairs(vals) do
tinsert(ret, k)
end
table.sort(ret)
return ret
end
local function getArgNums(args, prefix)
local nums = {}
for k, v in pairs(args) do
local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$')
if num then
tinsert(nums, tonumber(num))
end
end
table.sort(nums)
return nums
end
--------------------------------------------------------------------------------
-- Box class definition
--------------------------------------------------------------------------------
local box = {}
box.__index = box
function box.new()
local obj = {}
setmetatable(obj, box)
return obj
end
function box.getNamespaceId(ns)
if not ns then return end
if type(ns) == 'string' then
ns = lang:ucfirst(mw.ustring.lower(ns))
if ns == 'Main' then
ns = 0
end
end
local nsTable = mw.site.namespaces[ns]
if nsTable then
return nsTable.id
end
end
function box.getMboxType(nsid)
-- Gets the mbox type from a namespace number.
if nsid == 0 then
return 'ambox' -- main namespace
elseif nsid == 6 then
return 'imbox' -- file namespace
elseif nsid == 14 then
return 'cmbox' -- category namespace
else
local nsTable = mw.site.namespaces[nsid]
if nsTable and nsTable.isTalk then
return 'tmbox' -- any talk namespace
else
return 'ombox' -- other namespaces or invalid input
end
end
end
function box:addCat(ns, cat, sort)
if type(cat) ~= 'string' then return end
local nsVals = {'main', 'template', 'all'}
local tname
for i, val in ipairs(nsVals) do
if ns == val then
tname = ns .. 'Cats'
end
end
if not tname then
for i, val in ipairs(nsVals) do
nsVals[i] = format('"%s"', val)
end
error('無效的ns參數傳送到box:addCat;有效的數值為' .. mw.text.listToText(nsVals, '、', '或'))
end
self[tname] = self[tname] or {}
if type(sort) == 'string' then
tinsert(self[tname], format('[[Category:%s|%s]]', cat, sort))
else
tinsert(self[tname], format('[[Category:%s]]', cat))
end
end
function box:addClass(class)
if type(class) ~= 'string' then return end
self.classes = self.classes or {}
tinsert(self.classes, class)
end
function box:setTitle(args)
-- Get the title object and the namespace.
self.pageTitle = getTitleObject(args.page ~= '' and args.page)
self.title = self.pageTitle or mw.title.getCurrentTitle()
self.demospace = args.demospace ~= '' and args.demospace or nil
self.nsid = box.getNamespaceId(self.demospace) or self.title.namespace
end
function box:getConfig(boxType)
-- Get the box config data from the data page.
if boxType == 'mbox' then
boxType = box.getMboxType(self.nsid)
end
local cfg = cfgTables[boxType]
if not cfg then
local boxTypes = {}
for k, v in pairs(dataTables) do
tinsert(boxTypes, format('"%s"', k))
end
tinsert(boxTypes, '"mbox"')
error(format('無效的訊息框類型「%s」;有效的類型為%s', tostring(boxType), mw.text.listToText(boxTypes)), 2)
end
return cfg
end
function box:removeBlankArgs(cfg, args)
-- Only allow blank arguments for the parameter names listed in cfg.allowBlankParams.
local newArgs = {}
for k, v in pairs(args) do
if v ~= '' then
newArgs[k] = v
end
end
for i, param in ipairs(cfg.allowBlankParams or {}) do
newArgs[param] = args[param]
end
return newArgs
end
function box:setBoxParameters(cfg, args)
-- Get type data.
self.type = args.type
local typeData = cfg.types[self.type]
self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData and true or false
typeData = typeData or cfg.types[cfg.default]
self.typeClass = typeData.class
self.typeImage = typeData.image
-- Find if the box has been wrongly substituted.
if cfg.substCheck and args.subst == 'SUBST' then
self.isSubstituted = true
end
-- Find whether we are using a small message box.
if cfg.allowSmall and (
cfg.smallParam and args.small == cfg.smallParam
or not cfg.smallParam and yesno(args.small)
)
then
self.isSmall = true
else
self.isSmall = false
end
-- Add attributes, classes and styles.
if cfg.allowId then
self.id = args.id
self.name = args.name
if self.name then
self:addClass('box-' .. string.gsub(self.name,' ','_'))
end
end
self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks')
for _, class in ipairs(cfg.classes or {}) do
self:addClass(class)
end
if self.isSmall then
self:addClass(cfg.smallClass or 'mbox-small')
end
if yesno(args.hidden) then
self:addClass('infobox editsection')
end
self:addClass(self.typeClass)
self:addClass(args.class)
self.style = args.style
-- Set text style.
self.textstyle = args.textstyle
-- Find if we are on the template page or not. This functionality is only used if useCollapsibleTextFields is set,
-- or if both cfg.templateCategory and cfg.templateCategoryRequireName are set.
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
if self.useCollapsibleTextFields or cfg.templateCategory and cfg.templateCategoryRequireName then
self.name = args.name
if self.name then
local templateName = mw.ustring.match(self.name, '^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$') or self.name
templateName = 'Template:' .. templateName
self.templateTitle = getTitleObject(templateName)
end
self.isTemplatePage = self.templateTitle and mw.title.equals(self.title, self.templateTitle) or false
end
-- Process data for collapsible text fields. At the moment these are only used in {{ambox}}.
if self.useCollapsibleTextFields then
-- Get the self.issue value.
if self.isSmall and args.smalltext then
self.issue = args.smalltext
else
local sect
if args.sect == '' then
sect = '此' .. (cfg.sectionDefault or '頁面')
elseif type(args.sect) == 'string' then
sect = '此' .. args.sect
end
local issue = args.issue
issue = type(issue) == 'string' and issue ~= '' and issue or nil
local text = args.text
text = type(text) == 'string' and text or nil
local issues = {}
tinsert(issues, sect)
tinsert(issues, issue)
tinsert(issues, text)
self.issue = tconcat(issues)
end
-- Get the self.talk value.
local talk = args.talk
if talk == '' -- Show talk links on the template page or template subpages if the talk parameter is blank.
and self.templateTitle
and (mw.title.equals(self.templateTitle, self.title) or self.title:isSubpageOf(self.templateTitle))
then
talk = '#'
elseif talk == '' then
talk = nil
end
if talk then
-- If the talk value is a talk page, make a link to that page. Else assume that it's a section heading,
-- and make a link to the talk page of the current page with that section heading.
local talkTitle = getTitleObject(talk)
local talkArgIsTalkPage = true
if not talkTitle or not talkTitle.isTalkPage then
talkArgIsTalkPage = false
talkTitle = getTitleObject(self.title.text, mw.site.namespaces[self.title.namespace].talk.id)
end
if talkTitle and talkTitle.exists then
local talkText = '相關討論可見於'
if talkArgIsTalkPage then
talkText = format('%s[[%s|%s]].', talkText, talk, talkTitle.prefixedText)
else
talkText = format('%s[[%s#%s|討論頁]].', talkText, talkTitle.prefixedText, talk)
end
self.talk = talkText
end
end
-- Get other values.
local date
if args.date and args.date ~= '' then
date = args.date
elseif args.time == '' and self.isTemplatePage then
date = lang:formatDate('Y年n月j日')
elseif args.time and args.time ~= '' then
date = lang:formatDate('Y年n月j日', args.time)
end
if date then
local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月j日', date) -- 正規化日期
if ok then
date = tempdate
end
end
if date then
self.date = string.format(" <small class='date-container'>''(<span class='date'>%s</span>)''</small>", date)
end
if args.fix and args.fix ~= '' then
self.fix = format("<br /><small>%s</small>", args.fix)
else
self.fix = ''
end
self.info = args.info
end
-- Set the non-collapsible text field. At the moment this is used by all box types other than ambox,
-- and also by ambox when small=yes.
if self.isSmall then
self.text = args.smalltext or args.text
else
self.text = args.text
end
-- Set the below row.
self.below = cfg.below and args.below
-- General image settings.
self.imageCellDiv = not self.isSmall and cfg.imageCellDiv and true or false
self.imageEmptyCell = cfg.imageEmptyCell
if cfg.imageEmptyCellStyle then
self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px'
end
-- Left image settings.
local imageLeft = self.isSmall and args.smallimage or args.image
if cfg.imageCheckBlank and imageLeft ~= 'blank' and imageLeft ~= 'none'
or not cfg.imageCheckBlank and imageLeft ~= 'none'
then
self.imageLeft = imageLeft
if not imageLeft then
local imageSize = self.isSmall and (cfg.imageSmallSize or '30x30px') or '40x40px'
self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage or 'Imbox notice.png', imageSize)
end
end
-- Right image settings.
local imageRight = self.isSmall and args.smallimageright or args.imageright
if not (cfg.imageRightNone and imageRight == 'none') then
self.imageRight = imageRight
end
-- Add mainspace categories. At the moment these are only used in {{ambox}}.
if cfg.allowMainspaceCategories then
if args.cat then
args.cat1 = args.cat
end
self.catNums = getArgNums(args, 'cat')
if args.category then
args.category1 = args.category
end
self.categoryNums = getArgNums(args, 'category')
if args.all then
args.all1 = args.all
end
self.allNums = getArgNums(args, 'all')
self.categoryParamNums = union(self.catNums, self.categoryNums)
self.categoryParamNums = union(self.categoryParamNums, self.allNums)
-- The following is roughly equivalent to the old {{Ambox/category}}.
local date
local sortDay
local dayName = {
[1] = '㏠',
[2] = '㏡',
[3] = '㏢',
[4] = '㏣',
[5] = '㏤',
[6] = '㏥',
[7] = '㏦',
[8] = '㏧',
[9] = '㏨',
[10] = '㏩',
[11] = '㏪',
[12] = '㏫',
[13] = '㏬',
[14] = '㏭',
[15] = '㏮',
[16] = '㏯',
[17] = '㏰',
[18] = '㏱',
[19] = '㏲',
[20] = '㏳',
[21] = '㏴',
[22] = '㏵',
[23] = '㏶',
[24] = '㏷',
[25] = '㏸',
[26] = '㏹',
[27] = '㏺',
[28] = '㏻',
[29] = '㏼',
[30] = '㏽',
[31] = '㏾'
}
if args.date and args.date ~= '' then
date = args.date
local ok, tempdate = pcall(lang.formatDate, lang, 'Y年n月', date) -- 正規化日期
if ok then
date = tempdate
end
elseif args.time and args.time ~= '' then
date = lang:formatDate('Y年n月', args.time)
sortDay = lang:formatDate('j', args.time)
sortDay = tonumber(sortDay)
sortDay = dayName[sortDay]
end
date = type(date) == 'string' and date
local preposition = '自'
for _, num in ipairs(self.categoryParamNums) do
local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)]
local allCat = args['all' .. tostring(num)]
mainCat = type(mainCat) == 'string' and mainCat
allCat = type(allCat) == 'string' and allCat
if mainCat and date and date ~= '' then
local catTitle = format('%s%s%s', preposition, date, mainCat)
if sortDay then
self:addCat('main', catTitle, sortDay)
else
self:addCat('main', catTitle)
end
catTitle = getTitleObject('Category:' .. catTitle)
if not catTitle or not catTitle.exists then
self:addCat('main', '模板中使用无效日期参数的条目')
end
elseif mainCat and (not date or date == '') then
self:addCat('main', mainCat)
end
if allCat then
self:addCat('main', allCat)
end
end
end
-- Add template-namespace categories.
if cfg.templateCategory then
if cfg.templateCategoryRequireName then
if self.isTemplatePage then
self:addCat('template', cfg.templateCategory)
end
elseif not self.title.isSubpage then
self:addCat('template', cfg.templateCategory)
end
end
-- Add template error category.
if cfg.templateErrorCategory then
local templateErrorCategory = cfg.templateErrorCategory
local templateCat, templateSort
if not self.name and not self.title.isSubpage then
templateCat = templateErrorCategory
elseif self.isTemplatePage then
local paramsToCheck = cfg.templateErrorParamsToCheck or {}
local count = 0
for i, param in ipairs(paramsToCheck) do
if not args[param] then
count = count + 1
end
end
if count > 0 then
templateCat = templateErrorCategory
templateSort = tostring(count)
end
if self.categoryNums and #self.categoryNums > 0 then
templateCat = templateErrorCategory
templateSort = 'C'
end
end
self:addCat('template', templateCat, templateSort)
end
-- Categories for all namespaces.
if self.invalidTypeError then
local allSort = (self.nsid == 0 and 'Main:' or '') .. self.title.prefixedText
self:addCat('all', '需要修复的信息框', allSort)
end
if self.isSubstituted then
self:addCat('all', '錯誤使用替換引用的頁面')
end
-- Convert category tables to strings and pass them through [[Module:Category handler]].
self.categories = categoryHandler{
main = tconcat(self.mainCats or {}),
template = tconcat(self.templateCats or {}),
all = tconcat(self.allCats or {}),
nocat = args.nocat,
demospace = self.demospace,
page = self.pageTitle and self.pageTitle.prefixedText or nil
}
end
function box:export()
local root = mw.html.create()
-- Add the subst check error.
if self.isSubstituted and self.name then
root
:tag('b')
:addClass('error')
:wikitext(format(
'模板<code>%s[[Template:%s|%s]]%s</code>被錯誤地替代。',
mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')
))
end
-- Create the box table.
local boxTable = root:tag('table')
boxTable
:attr('id', self.id)
for i, class in ipairs(self.classes or {}) do
boxTable
:addClass(class)
end
boxTable
:cssText(self.style)
:attr('role', 'presentation')
-- Add the left-hand image.
local row = boxTable:tag('tr')
if self.imageLeft then
local imageLeftCell = row:tag('td'):addClass('mbox-image')
if self.imageCellDiv then
-- If we are using a div, redefine imageLeftCell so that the image is inside it.
-- Divs use style="width: 52px;", which limits the image width to 52px. If any
-- images in a div are wider than that, they may overlap with the text or cause
-- other display problems.
imageLeftCell = imageLeftCell:tag('div'):css('width', '52px')
end
imageLeftCell
:wikitext(self.imageLeft)
elseif self.imageEmptyCell then
-- Some message boxes define an empty cell if no image is specified, and some don't.
-- The old template code in templates where empty cells are specified gives the following hint:
-- "No image. Cell with some width or padding necessary for text cell to have 100% width."
row:tag('td')
:addClass('mbox-empty-cell')
:cssText(self.imageEmptyCellStyle)
end
-- Add the text.
local textCell = row:tag('td'):addClass('mbox-text')
if self.useCollapsibleTextFields then
-- The message box uses advanced text parameters that allow things to be collapsible. At the
-- moment, only ambox uses this.
textCell
:cssText(self.textstyle)
local textCellSpan = textCell:tag('div')
textCellSpan
:addClass('mbox-text-span')
:wikitext(self.issue)
if not self.isSmall then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.talk and self.talk)
end
textCellSpan
:wikitext(self.date and self.date)
if not self.isSmall and self.fix ~= '' then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.fix and self.fix)
end
if not self.isSmall then
textCellSpan
:tag('span')
:addClass('hide-when-compact')
:wikitext(self.info and self.info)
end
else
-- Default text formatting - anything goes.
textCell
:cssText(self.textstyle)
:wikitext(self.text)
end
-- Add the right-hand image.
if self.imageRight then
local imageRightCell = row:tag('td'):addClass('mbox-imageright')
if self.imageCellDiv then
imageRightCell = imageRightCell:tag('div'):css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.
end
imageRightCell
:wikitext(self.imageRight)
end
-- Add the below row.
if self.below then
boxTable:tag('tr')
:tag('td')
:attr('colspan', self.imageRight and '3' or '2')
:addClass('mbox-text')
:cssText(self.textstyle)
:wikitext(self.below)
end
-- Add error message for invalid type parameters.
if self.invalidTypeError then
root
:tag('div')
:css('text-align', 'center')
:wikitext(format('此訊息框使用無效的「type=%s」參數,需要修復。', self.type or ''))
end
-- Add categories.
root
:wikitext(self.categories)
return tostring(root)
end
local function main(boxType, args)
local outputBox = box.new()
outputBox:setTitle(args)
local cfg = outputBox:getConfig(boxType)
args = outputBox:removeBlankArgs(cfg, args)
outputBox:setBoxParameters(cfg, args)
return outputBox:export()
end
local function makeWrapper(boxType)
return function (frame)
local args = getArgs(frame, {trim = false, removeBlanks = false})
return main(boxType, args)
end
end
local p = {
main = main,
mbox = makeWrapper('mbox')
}
for boxType in pairs(cfgTables) do
p[boxType] = makeWrapper(boxType)
end
return p
272fc832b204569beebe8b740e600f3f69aafc11
Module:Category handler
828
60
115
114
2024-08-02T10:51:17Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- CATEGORY HANDLER --
-- --
-- This module implements the {{category handler}} template in Lua, --
-- with a few improvements: all namespaces and all namespace aliases --
-- are supported, and namespace names are detected automatically for --
-- the local wiki. This module requires [[Module:Namespace detect]] --
-- and [[Module:Yesno]] to be available on the local wiki. It can be --
-- configured for different wikis by altering the values in --
-- [[Module:Category handler/config]], and pages can be blacklisted --
-- from categorisation by using [[Module:Category handler/blacklist]]. --
-- --
--------------------------------------------------------------------------------
-- Load required modules
local yesno = require('Module:Yesno')
-- Lazily load things we don't always need
local mShared, mappings
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function trimWhitespace(s, removeBlanks)
if type(s) ~= 'string' then
return s
end
s = s:match('^%s*(.-)%s*$')
if removeBlanks then
if s ~= '' then
return s
else
return nil
end
else
return s
end
end
--------------------------------------------------------------------------------
-- CategoryHandler class
--------------------------------------------------------------------------------
local CategoryHandler = {}
CategoryHandler.__index = CategoryHandler
function CategoryHandler.new(data, args)
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
-- Set the title object
do
local pagename = obj:parameter('demopage')
local success, titleObj
if pagename then
success, titleObj = pcall(mw.title.new, pagename)
end
if success and titleObj then
obj.title = titleObj
if titleObj == mw.title.getCurrentTitle() then
obj._usesCurrentTitle = true
end
else
obj.title = mw.title.getCurrentTitle()
obj._usesCurrentTitle = true
end
end
-- Set suppression parameter values
for _, key in ipairs{'nocat', 'categories'} do
local value = obj:parameter(key)
value = trimWhitespace(value, true)
obj['_' .. key] = yesno(value)
end
do
local subpage = obj:parameter('subpage')
local category2 = obj:parameter('category2')
if type(subpage) == 'string' then
subpage = mw.ustring.lower(subpage)
end
if type(category2) == 'string' then
subpage = mw.ustring.lower(category2)
end
obj._subpage = trimWhitespace(subpage, true)
obj._category2 = trimWhitespace(category2) -- don't remove blank values
end
return obj
end
function CategoryHandler:parameter(key)
local parameterNames = self._data.parameters[key]
local pntype = type(parameterNames)
if pntype == 'string' or pntype == 'number' then
return self._args[parameterNames]
elseif pntype == 'table' then
for _, name in ipairs(parameterNames) do
local value = self._args[name]
if value ~= nil then
return value
end
end
return nil
else
error(string.format(
'invalid config key "%s"',
tostring(key)
), 2)
end
end
function CategoryHandler:isSuppressedByArguments()
return
-- See if a category suppression argument has been set.
self._nocat == true
or self._categories == false
or (
self._category2
and self._category2 ~= self._data.category2Yes
and self._category2 ~= self._data.category2Negative
)
-- Check whether we are on a subpage, and see if categories are
-- suppressed based on our subpage status.
or self._subpage == self._data.subpageNo and self.title.isSubpage
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
end
function CategoryHandler:shouldSkipBlacklistCheck()
-- Check whether the category suppression arguments indicate we
-- should skip the blacklist check.
return self._nocat == false
or self._categories == true
or self._category2 == self._data.category2Yes
end
function CategoryHandler:matchesBlacklist()
if self._usesCurrentTitle then
return self._data.currentTitleMatchesBlacklist
else
mShared = mShared or require('Module:Category handler/shared')
return mShared.matchesBlacklist(
self.title.prefixedText,
mw.loadData('Module:Category handler/blacklist')
)
end
end
function CategoryHandler:isSuppressed()
-- Find if categories are suppressed by either the arguments or by
-- matching the blacklist.
return self:isSuppressedByArguments()
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
end
function CategoryHandler:getNamespaceParameters()
if self._usesCurrentTitle then
return self._data.currentTitleNamespaceParameters
else
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
return mShared.getNamespaceParameters(
self.title,
mappings
)
end
end
function CategoryHandler:namespaceParametersExist()
-- Find whether any namespace parameters have been specified.
-- We use the order "all" --> namespace params --> "other" as this is what
-- the old template did.
if self:parameter('all') then
return true
end
if not mappings then
mShared = mShared or require('Module:Category handler/shared')
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
end
for ns, params in pairs(mappings) do
for i, param in ipairs(params) do
if self._args[param] then
return true
end
end
end
if self:parameter('other') then
return true
end
return false
end
function CategoryHandler:getCategories()
local params = self:getNamespaceParameters()
local nsCategory
for i, param in ipairs(params) do
local value = self._args[param]
if value ~= nil then
nsCategory = value
break
end
end
if nsCategory ~= nil or self:namespaceParametersExist() then
-- Namespace parameters exist - advanced usage.
if nsCategory == nil then
nsCategory = self:parameter('other')
end
local ret = {self:parameter('all')}
local numParam = tonumber(nsCategory)
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
-- nsCategory is an integer
ret[#ret + 1] = self._args[numParam]
else
ret[#ret + 1] = nsCategory
end
if #ret < 1 then
return nil
else
return table.concat(ret)
end
elseif self._data.defaultNamespaces[self.title.namespace] then
-- Namespace parameters don't exist, simple usage.
return self._args[1]
end
return nil
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- Used for testing purposes.
return {
CategoryHandler = CategoryHandler
}
end
function p._main(args, data)
data = data or mw.loadData('Module:Category handler/data')
local handler = CategoryHandler.new(data, args)
if handler:isSuppressed() then
return nil
end
return handler:getCategories()
end
function p.main(frame, data)
data = data or mw.loadData('Module:Category handler/data')
local args = require('Module:Arguments').getArgs(frame, {
wrappers = data.wrappers,
valueFunc = function (k, v)
v = trimWhitespace(v)
if type(k) == 'number' then
if v ~= '' then
return v
else
return nil
end
else
return v
end
end
})
return p._main(args, data)
end
return p
b74dd63857b24904ac452429b11213f18647471f
Module:Message box/configuration
828
61
117
116
2024-08-02T10:51:17Z
黑茶
2
导入1个版本
Scribunto
text/plain
local ambox = {
types = {
speedy = {
class = 'ambox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ambox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'ambox-content',
image = 'Ambox important.svg'
},
style = {
class = 'ambox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ambox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ambox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'ambox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
allowBlankParams = {'talk', 'sect', 'date', 'issue', 'fix', 'subst', 'hidden'},
allowSmall = true,
smallParam = 'left',
smallClass = 'mbox-small-left',
substCheck = true,
classes = {'metadata', 'ambox'},
usePlainlinksParam = true,
allowId = true,
imageEmptyCell = true,
imageCheckBlank = true,
imageSmallSize = '20x20px',
imageCellDiv = true,
useCollapsibleTextFields = true,
imageRightNone = true,
sectionDefault = '條目',
allowMainspaceCategories = true,
templateCategory = '條目訊息模板',
templateCategoryRequireName = true,
templateErrorCategory = '缺少參數的條目訊息模板',
templateErrorParamsToCheck = {'issue', 'fix', 'subst'}
}
local cmbox = {
types = {
speedy = {
class = 'cmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'cmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'cmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'cmbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'cmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'cmbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'cmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'cmbox'},
usePlainlinksParam = true,
imageEmptyCell = true
}
local fmbox = {
types = {
warning = {
class = 'fmbox-warning',
image = 'Ambox warning pn.svg'
},
editnotice = {
class = 'fmbox-editnotice',
image = 'Information icon4.svg'
},
system = {
class = 'fmbox-system',
image = 'Information icon4.svg'
}
},
default = 'system',
showInvalidTypeError = true,
allowId = true,
classes = {'fmbox'},
usePlainlinksParam = true,
imageEmptyCell = false,
imageRightNone = false
}
local imbox = {
types = {
speedy = {
class = 'imbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'imbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'imbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'imbox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'imbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'imbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
license = {
class = 'imbox-license',
image = 'Imbox license.png'
},
featured = {
class = 'imbox-featured',
image = 'Cscr-featured.svg'
},
notice = {
class = 'imbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'imbox'},
usePlainlinksParam = true,
imageEmptyCell = true,
below = true,
templateCategory = '檔案訊息模板'
}
local ombox = {
types = {
speedy = {
class = 'ombox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'ombox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'ombox-content',
image = 'Ambox important.svg'
},
style = {
class = 'ombox-style',
image = 'Edit-clear.svg'
},
move = {
class = 'ombox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'ombox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'ombox-notice',
image = 'Information icon4.svg'
},
note = {
class = 'ombox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'ombox'},
usePlainlinksParam = true,
allowSmall = true,
imageEmptyCell = true,
imageRightNone = true
}
local tmbox = {
types = {
speedy = {
class = 'tmbox-speedy',
image = 'Ambox warning pn.svg'
},
delete = {
class = 'tmbox-delete',
image = 'Ambox warning pn.svg'
},
content = {
class = 'tmbox-content',
image = 'Ambox important.svg'
},
style = {
class = 'tmbox-style',
image = 'Edit-clear.svg '
},
move = {
class = 'tmbox-move',
image = 'Merge-split-transwiki default.svg'
},
protection = {
class = 'tmbox-protection',
image = 'Semi-protection-shackle-keyhole.svg'
},
notice = {
class = 'tmbox-notice',
image = 'Information icon4.svg'
}
},
default = 'notice',
showInvalidTypeError = true,
classes = {'tmbox'},
usePlainlinksParam = true,
allowId = true,
allowSmall = true,
imageRightNone = true,
imageEmptyCell = true,
imageEmptyCellStyle = true,
templateCategory = '討論訊息模板'
}
return {
ambox = ambox,
cmbox = cmbox,
fmbox = fmbox,
imbox = imbox,
ombox = ombox,
tmbox = tmbox
}
d6b253dd26d5c1b7843394d8c6756b0868e70b6c
Module:Effective protection level
828
62
119
118
2024-08-02T10:51:17Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
-- Returns the permission required to perform a given action on a given title.
-- If no title is specified, the title of the page being displayed is used.
function p._main(action, pagename)
local title
if type(pagename) == 'table' and pagename.prefixedText then
title = pagename
elseif pagename then
title = mw.title.new(pagename)
else
title = mw.title.getCurrentTitle()
end
pagename = title.prefixedText
if action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' and action ~= 'undelete' then
error( 'First parameter must be one of edit, move, create, upload, undelete', 2 )
end
if title.namespace == 8 then -- MediaWiki namespace
if title.text:sub(-3) == '.js' or title.text:sub(-4) == '.css' or title.contentModel == 'javascript' or title.contentModel == 'css' then -- site JS or CSS page
return 'interfaceadmin'
else -- any non-JS/CSS MediaWiki page
return 'sysop'
end
elseif title.namespace == 2 and title.isSubpage then
if title.contentModel == 'javascript' or title.contentModel == 'css' then -- user JS or CSS page
return 'interfaceadmin'
elseif title.contentModel == 'json' then -- user JSON page
return 'sysop'
end
end
if action == 'undelete' then
return 'sysop'
end
local level = title.protectionLevels[action] and title.protectionLevels[action][1]
if level == 'sysop' or level == 'editprotected' then
return 'sysop'
elseif title.cascadingProtection.restrictions[action] and title.cascadingProtection.restrictions[action][1] then -- used by a cascading-protected page
return 'sysop'
elseif level == 'templateeditor' then
return 'templateeditor'
elseif action == 'move' then
local blacklistentry = mw.ext.TitleBlacklist.test('edit', pagename) -- Testing action edit is correct, since this is for the source page. The target page name gets tested with action move.
if blacklistentry and not blacklistentry.params.autoconfirmed then
return 'sysop'
elseif title.namespace == 6 then
return 'filemover'
elseif level == 'extendedconfirmed' then
return 'extendedconfirmed'
else
return 'autoconfirmed'
end
end
local blacklistentry = mw.ext.TitleBlacklist.test(action, pagename)
if blacklistentry then
if not blacklistentry.params.autoconfirmed then
return 'sysop'
elseif level == 'extendedconfirmed' then
return 'extendedconfirmed'
else
return 'autoconfirmed'
end
elseif level == 'editsemiprotected' then -- create-semiprotected pages return this for some reason
return 'autoconfirmed'
elseif level then
return level
elseif action == 'upload' then
return 'autoconfirmed'
else
return '*'
end
end
setmetatable(p, { __index = function(t, k)
return function(frame)
return t._main(k, frame.args[1])
end
end })
return p
d22097a8a4da3e18514a12fbe2c417c4f4be91f2
Module:No globals
828
63
121
120
2024-08-02T10:51:18Z
黑茶
2
导入1个版本
Scribunto
text/plain
local mt = getmetatable(_G) or {}
function mt.__index (t, k)
if k ~= 'arg' then
error('尝试读取空全局变量:' .. tostring(k), 2)
end
return nil
end
function mt.__newindex(t, k, v)
if k ~= 'arg' then
error('尝试写入全局变量:' .. tostring(k), 2)
end
rawset(t, k, v)
end
setmetatable(_G, mt)
75f542ec50e6eec7c23271b53c09f1c648b88f77
Module:Category handler/data
828
64
123
122
2024-08-02T10:51:18Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module assembles data to be passed to [[Module:Category handler]] using
-- mw.loadData. This includes the configuration data and whether the current
-- page matches the title blacklist.
local data = require('Module:Category handler/config')
local mShared = require('Module:Category handler/shared')
local blacklist = require('Module:Category handler/blacklist')
local title = mw.title.getCurrentTitle()
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(
title.prefixedText,
blacklist
)
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(
title,
mShared.getParamMappings()
)
return data
abbc68048ff698e88dda06b64ecf384bbf583120
Module:Category handler/config
828
65
125
124
2024-08-02T10:51:18Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- [[Module:Category handler]] configuration data --
-- Language-specific parameter names and values can be set here. --
-- For blacklist config, see [[Module:Category handler/blacklist]]. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- foo = 'parameter name', --
-- --
-- To add multiple names, you can use this format: --
-- --
-- foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'}, --
--------------------------------------------------------------------------------
cfg.parameters = {
-- The nocat and categories parameter suppress
-- categorisation. They are used with Module:Yesno, and work as follows:
--
-- cfg.nocat:
-- Result of yesno() Effect
-- true Categorisation is suppressed
-- false Categorisation is allowed, and
-- the blacklist check is skipped
-- nil Categorisation is allowed
--
-- cfg.categories:
-- Result of yesno() Effect
-- true Categorisation is allowed, and
-- the blacklist check is skipped
-- false Categorisation is suppressed
-- nil Categorisation is allowed
nocat = 'nocat',
categories = 'categories',
-- The parameter name for the legacy "category2" parameter. This skips the
-- blacklist if set to the cfg.category2Yes value, and suppresses
-- categorisation if present but equal to anything other than
-- cfg.category2Yes or cfg.category2Negative.
category2 = 'category2',
-- cfg.subpage is the parameter name to specify how to behave on subpages.
subpage = 'subpage',
-- The parameter for data to return in all namespaces.
all = 'all',
-- The parameter name for data to return if no data is specified for the
-- namespace that is detected.
other = 'other',
-- The parameter name used to specify a page other than the current page;
-- used for testing and demonstration.
demopage = 'page',
}
--------------------------------------------------------------------------------
-- Parameter values --
-- These are set values that can be used with certain parameters. Only one --
-- value can be specified, like this: --
-- --
-- cfg.foo = 'value name' -- --
--------------------------------------------------------------------------------
-- The following settings are used with the cfg.category2 parameter. Setting
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2
-- is present but equal to anything other than cfg.category2Yes or
-- cfg.category2Negative then it supresses cateogrisation.
cfg.category2Yes = 'yes'
cfg.category2Negative = '¬'
-- The following settings are used with the cfg.subpage parameter.
-- cfg.subpageNo is the value to specify to not categorise on subpages;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.
cfg.subpageNo = 'no'
cfg.subpageOnly = 'only'
--------------------------------------------------------------------------------
-- Default namespaces --
-- This is a table of namespaces to categorise by default. The keys are the --
-- namespace numbers. --
--------------------------------------------------------------------------------
cfg.defaultNamespaces = {
[ 0] = true, -- main
[ 6] = true, -- file
[ 12] = true, -- help
[ 14] = true, -- category
[100] = true, -- portal
[108] = true, -- book
}
--------------------------------------------------------------------------------
-- Wrappers --
-- This is a wrapper template or a list of wrapper templates to be passed to --
-- [[Module:Arguments]]. --
--------------------------------------------------------------------------------
cfg.wrappers = 'Template:Category handler'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
373cd107b13a5b00e6a1b7e66a749f12502c849d
Module:Category handler/shared
828
66
127
126
2024-08-02T10:51:19Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module contains shared functions used by [[Module:Category handler]]
-- and its submodules.
local p = {}
function p.matchesBlacklist(page, blacklist)
for i, pattern in ipairs(blacklist) do
local match = mw.ustring.match(page, pattern)
if match then
return true
end
end
return false
end
function p.getParamMappings(useLoadData)
local dataPage = 'Module:Namespace detect/data'
if useLoadData then
return mw.loadData(dataPage).mappings
else
return require(dataPage).mappings
end
end
function p.getNamespaceParameters(titleObj, mappings)
-- We don't use title.nsText for the namespace name because it adds
-- underscores.
local mappingsKey
if titleObj.isTalkPage then
mappingsKey = 'talk'
else
mappingsKey = mw.site.namespaces[titleObj.namespace].name
end
mappingsKey = mw.ustring.lower(mappingsKey)
return mappings[mappingsKey] or {}
end
return p
d2d5de1a031e6ce97c242cbfa8afe7a92cb9eca5
Module:Category handler/blacklist
828
67
129
128
2024-08-02T10:51:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^那艺娜维基:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^那艺娜维基:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
939eea9afe7dd0de8be68d71a9cbccfca2c3d6ee
Module:Namespace detect/data
828
68
131
130
2024-08-02T10:51:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect data --
-- This module holds data for [[Module:Namespace detect]] to be loaded per --
-- page, rather than per #invoke, for performance reasons. --
--------------------------------------------------------------------------------
local cfg = require('Module:Namespace detect/config')
local function addKey(t, key, defaultKey)
if key ~= defaultKey then
t[#t + 1] = key
end
end
-- Get a table of parameters to query for each default parameter name.
-- This allows wikis to customise parameter names in the cfg table while
-- ensuring that default parameter names will always work. The cfg table
-- values can be added as a string, or as an array of strings.
local defaultKeys = {
'main',
'talk',
'other',
'subjectns',
'demospace',
'demopage'
}
local argKeys = {}
for i, defaultKey in ipairs(defaultKeys) do
argKeys[defaultKey] = {defaultKey}
end
for defaultKey, t in pairs(argKeys) do
local cfgValue = cfg[defaultKey]
local cfgValueType = type(cfgValue)
if cfgValueType == 'string' then
addKey(t, cfgValue, defaultKey)
elseif cfgValueType == 'table' then
for i, key in ipairs(cfgValue) do
addKey(t, key, defaultKey)
end
end
cfg[defaultKey] = nil -- Free the cfg value as we don't need it any more.
end
local function getParamMappings()
--[[
-- Returns a table of how parameter names map to namespace names. The keys
-- are the actual namespace names, in lower case, and the values are the
-- possible parameter names for that namespace, also in lower case. The
-- table entries are structured like this:
-- {
-- [''] = {'main'},
-- ['wikipedia'] = {'wikipedia', 'project', 'wp'},
-- ...
-- }
--]]
local mappings = {}
local mainNsName = mw.site.subjectNamespaces[0].name
mainNsName = mw.ustring.lower(mainNsName)
mappings[mainNsName] = mw.clone(argKeys.main)
mappings['talk'] = mw.clone(argKeys.talk)
for nsid, ns in pairs(mw.site.subjectNamespaces) do
if nsid ~= 0 then -- Exclude main namespace.
local nsname = mw.ustring.lower(ns.name)
local canonicalName = mw.ustring.lower(ns.canonicalName)
mappings[nsname] = {nsname}
if canonicalName ~= nsname then
table.insert(mappings[nsname], canonicalName)
end
for _, alias in ipairs(ns.aliases) do
table.insert(mappings[nsname], mw.ustring.lower(alias))
end
end
end
return mappings
end
return {
argKeys = argKeys,
cfg = cfg,
mappings = getParamMappings()
}
d224f42a258bc308ef3ad8cc8686cd7a4f47d005
Module:Namespace detect/config
828
69
133
132
2024-08-02T10:51:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Namespace detect configuration data --
-- --
-- This module stores configuration data for Module:Namespace detect. Here --
-- you can localise the module to your wiki's language. --
-- --
-- To activate a configuration item, you need to uncomment it. This means --
-- that you need to remove the text "-- " at the start of the line. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Parameter names --
-- These configuration items specify custom parameter names. Values added --
-- here will work in addition to the default English parameter names. --
-- To add one extra name, you can use this format: --
-- --
-- cfg.foo = 'parameter name' --
-- --
-- To add multiple names, you can use this format: --
-- --
-- cfg.foo = {'parameter name 1', 'parameter name 2', 'parameter name 3'} --
--------------------------------------------------------------------------------
---- This parameter displays content for the main namespace:
-- cfg.main = 'main'
---- This parameter displays in talk namespaces:
-- cfg.talk = 'talk'
---- This parameter displays content for "other" namespaces (namespaces for which
---- parameters have not been specified):
-- cfg.other = 'other'
---- This parameter makes talk pages behave as though they are the corresponding
---- subject namespace. Note that this parameter is used with [[Module:Yesno]].
---- Edit that module to change the default values of "yes", "no", etc.
-- cfg.subjectns = 'subjectns'
---- This parameter sets a demonstration namespace:
-- cfg.demospace = 'demospace'
---- This parameter sets a specific page to compare:
cfg.demopage = 'page'
--------------------------------------------------------------------------------
-- Table configuration --
-- These configuration items allow customisation of the "table" function, --
-- used to generate a table of possible parameters in the module --
-- documentation. --
--------------------------------------------------------------------------------
---- The header for the namespace column in the wikitable containing the list of
---- possible subject-space parameters.
-- cfg.wikitableNamespaceHeader = 'Namespace'
---- The header for the wikitable containing the list of possible subject-space
---- parameters.
-- cfg.wikitableAliasesHeader = 'Aliases'
--------------------------------------------------------------------------------
-- End of configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line.
0e4ff08d13c4b664d66b32c232deb129b77c1a56
Template:Tlx
10
70
135
134
2024-08-02T10:51:21Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><!--
--><code><!--
--><nowiki>{{</nowiki>{{#if:{{{subst|}}} |[[Help:替换引用|subst]]:}}<!--
-->[[{{{LANG|}}}{{{SISTER|}}}{{ns:Template}}:{{{1|}}}|{{{1|}}}]]<!--
-->{{#if:{{{2|}}} ||{{{2}}}}}<!--
-->{{#if:{{{3|}}} ||{{{3}}}}}<!--
-->{{#if:{{{4|}}} ||{{{4}}}}}<!--
-->{{#if:{{{5|}}} ||{{{5}}}}}<!--
-->{{#if:{{{6|}}} ||{{{6}}}}}<!--
-->{{#if:{{{7|}}} ||{{{7}}}}}<!--
-->{{#if:{{{8|}}} ||{{{8}}}}}<!--
-->{{#if:{{{9|}}} ||{{{9}}}}}<!--
-->{{#if:{{{10|}}} ||{{{10}}}}}<!--
-->{{#if:{{{11|}}} ||{{{11}}}}}<!--
-->{{#if:{{{12|}}} ||{{{12}}}}}<!--
-->{{#if:{{{13|}}} ||{{{13}}}}}<!--
-->{{#if:{{{14|}}} ||{{{14}}}}}<!--
-->{{#if:{{{15|}}} ||{{{15}}}}}<!--
-->{{#if:{{{16|}}} ||{{{16}}}}}<!--
-->{{#if:{{{17|}}} ||{{{17}}}}}<!--
-->{{#if:{{{18|}}} ||{{{18}}}}}<!--
-->{{#if:{{{19|}}} ||{{{19}}}}}<!--
-->{{#if:{{{20|}}} ||{{{20}}}}}<!--
-->{{#if:{{{21|}}} ||''...''}}<!--
--><nowiki>}}</nowiki><!--
--></code><!--
--></includeonly><noinclude>
{{Documentation}}</noinclude>
d8d004509af027beddd80b75c1e20c88dfabbc76
Module:Separated entries
828
71
137
136
2024-08-02T10:51:21Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module takes positional parameters as input and concatenates them with
-- an optional separator. The final separator (the "conjunction") can be
-- specified independently, enabling natural-language lists like
-- "foo, bar, baz and qux".
local compressSparseArray = require('Module:TableTools').compressSparseArray
local p = {}
function p._main(args)
local separator = args.separator
-- Decode (convert to Unicode) HTML escape sequences, such as " " for space.
and mw.text.decode(args.separator) or ''
local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator
-- Discard named parameters.
local values = compressSparseArray(args)
return mw.text.listToText(values, separator, conjunction)
end
local function makeInvokeFunction(separator, conjunction)
return function (frame)
local args = require('Module:Arguments').getArgs(frame)
args.separator = separator or args.separator
args.conjunction = conjunction or args.conjunction
return p._main(args)
end
end
p.main = makeInvokeFunction()
p.br = makeInvokeFunction('<br />')
p.comma = makeInvokeFunction(mw.message.new('comma-separator'):plain())
return p
b8d9de70633108b00f860aed20a52b749fdeca15
Module:TableTools
828
72
139
138
2024-08-02T10:51:22Z
黑茶
2
导入1个版本
Scribunto
text/plain
------------------------------------------------------------------------------------
-- TableTools --
-- --
-- This module includes a number of functions for dealing with Lua tables. --
-- It is a meta-module, meant to be called from other Lua modules, and should not --
-- be called directly from #invoke. --
------------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local p = {}
-- Define often-used variables and functions.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
function p.isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity
end
------------------------------------------------------------------------------------
-- isNan
--
-- This function returns true if the given number is a NaN value, and false if
-- not. Although it doesn't operate on tables, it is included here as it is useful
-- for determining whether a value can be a valid table key. Lua will generate an
-- error if a NaN is used as a table key.
------------------------------------------------------------------------------------
function p.isNan(v)
return type(v) == 'number' and v ~= v
end
------------------------------------------------------------------------------------
-- shallowClone
--
-- This returns a clone of a table. The value returned is a new table, but all
-- subtables and functions are shared. Metamethods are respected, but the returned
-- table will have no metatable of its own.
------------------------------------------------------------------------------------
function p.shallowClone(t)
checkType('shallowClone', 1, t, 'table')
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- This removes duplicate values from an array. Non-positive-integer keys are
-- ignored. The earliest value is kept, and all subsequent duplicate values are
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
function p.removeDuplicates(arr)
checkType('removeDuplicates', 1, arr, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for _, v in ipairs(arr) do
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
else
if not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
end
return ret
end
------------------------------------------------------------------------------------
-- numKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in numerical order.
------------------------------------------------------------------------------------
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- affixNums
--
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return
-- {1, 3, 6}.
------------------------------------------------------------------------------------
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- numData
--
-- Given a table with keys like {"foo1", "bar1", "foo2", "baz2"}, returns a table
-- of subtables in the format
-- {[1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text'}}.
-- Keys that don't end with an integer are stored in a subtable named "other". The
-- compress option compresses the table so that it can be iterated over with
-- ipairs.
------------------------------------------------------------------------------------
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Positional parameters match the blank string; put them at the start of the subtable instead.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- This takes an array with one or more nil values, and removes the nil values
-- while preserving the order, so that the array can be safely traversed with
-- ipairs.
------------------------------------------------------------------------------------
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- This is an iterator for sparse arrays. It can be used like ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- size
--
-- This returns the size of a key/value pair table. It will also work on arrays,
-- but for arrays it is more efficient to use the # operator.
------------------------------------------------------------------------------------
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for _ in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- "number" < "string", so numbers will be sorted before strings.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then
return tostring(item1) < tostring(item2)
else
return item1 < item2
end
end
------------------------------------------------------------------------------------
-- keysToList
--
-- Returns an array of the keys in a table, sorted using either a default
-- comparison function or a custom keySort function.
------------------------------------------------------------------------------------
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'})
end
local arr = {}
local index = 1
for k in pairs(t) do
arr[index] = k
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(arr, keySort)
end
return arr
end
------------------------------------------------------------------------------------
-- sortedPairs
--
-- Iterates through a table, with the keys sorted using the keysToList function.
-- If there are only numerical keys, sparseIpairs is probably more efficient.
------------------------------------------------------------------------------------
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local arr = p.keysToList(t, keySort, true)
local i = 0
return function ()
i = i + 1
local key = arr[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- isArray
--
-- Returns true if the given value is a table and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArray(v)
if type(v) ~= 'table' then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- isArrayLike
--
-- Returns true if the given value is iterable and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArrayLike(v)
if not pcall(pairs, v) then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- invert
--
-- Transposes the keys and values in an array. For example, {"a", "b", "c"} ->
-- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to
-- the index of the last duplicate) and NaN values are ignored.
------------------------------------------------------------------------------------
function p.invert(arr)
checkType("invert", 1, arr, "table")
local isNan = p.isNan
local map = {}
for i, v in ipairs(arr) do
if not isNan(v) then
map[v] = i
end
end
return map
end
------------------------------------------------------------------------------------
-- listToSet
--
-- Creates a set from the array part of the table. Indexing the set by any of the
-- values of the array returns true. For example, {"a", "b", "c"} ->
-- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them
-- never equal to any value (including other NaNs or even themselves).
------------------------------------------------------------------------------------
function p.listToSet(arr)
checkType("listToSet", 1, arr, "table")
local isNan = p.isNan
local set = {}
for _, v in ipairs(arr) do
if not isNan(v) then
set[v] = true
end
end
return set
end
------------------------------------------------------------------------------------
-- deepCopy
--
-- Recursive deep copy function. Preserves identities of subtables.
------------------------------------------------------------------------------------
local function _deepCopy(orig, includeMetatable, already_seen)
-- Stores copies of tables indexed by the original table.
already_seen = already_seen or {}
local copy = already_seen[orig]
if copy ~= nil then
return copy
end
if type(orig) == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen)
end
already_seen[orig] = copy
if includeMetatable then
local mt = getmetatable(orig)
if mt ~= nil then
local mt_copy = _deepCopy(mt, includeMetatable, already_seen)
setmetatable(copy, mt_copy)
already_seen[mt] = mt_copy
end
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen)
end
------------------------------------------------------------------------------------
-- sparseConcat
--
-- Concatenates all values in the table that are indexed by a number, in order.
-- sparseConcat{a, nil, c, d} => "acd"
-- sparseConcat{nil, b, c, d} => "bcd"
------------------------------------------------------------------------------------
function p.sparseConcat(t, sep, i, j)
local arr = {}
local arr_i = 0
for _, v in p.sparseIpairs(t) do
arr_i = arr_i + 1
arr[arr_i] = v
end
return table.concat(arr, sep, i, j)
end
------------------------------------------------------------------------------------
-- length
--
-- Finds the length of an array, or of a quasi-array with keys such as "data1",
-- "data2", etc., using an exponential search algorithm. It is similar to the
-- operator #, but may return a different value when there are gaps in the array
-- portion of the table. Intended to be used on data loaded with mw.loadData. For
-- other tables, use #.
-- Note: #frame.args in frame object always be set to 0, regardless of the number
-- of unnamed template parameters, so use this function for frame.args.
------------------------------------------------------------------------------------
function p.length(t, prefix)
-- requiring module inline so that [[Module:Exponential search]] which is
-- only needed by this one function doesn't get millions of transclusions
local expSearch = require("Module:Exponential search")
checkType('length', 1, t, 'table')
checkType('length', 2, prefix, 'string', true)
return expSearch(function (i)
local key
if prefix then
key = prefix .. tostring(i)
else
key = i
end
return t[key] ~= nil
end) or 0
end
------------------------------------------------------------------------------------
-- inArray
--
-- Returns true if valueToFind is a member of the array, and false otherwise.
------------------------------------------------------------------------------------
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- if valueToFind is nil, error?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end
return p
085e7094ac84eb0132ee65822cf3f69cd8ba3d81
Template:Navbox
10
73
141
140
2024-08-02T10:51:22Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke: Navbox | navbox }}</includeonly><noinclude>{{documentation}}<!-- Add categories and interwikis to the /doc sub-page --></noinclude>
2b5d285f265745c44fc40f51d6e9bfa0a05efc9a
Module:String
828
74
143
142
2024-08-02T10:51:22Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[
This module is intended to provide access to basic string functions.
Most of the functions provided here can be invoked with named parameters,
unnamed parameters, or a mixture. If named parameters are used, Mediawiki will
automatically remove any leading or trailing whitespace from the parameter.
Depending on the intended use, it may be advantageous to either preserve or
remove such whitespace.
Global options
ignore_errors: If set to 'true' or 1, any error condition will result in
an empty string being returned rather than an error message.
error_category: If an error occurs, specifies the name of a category to
include with the error message. The default category is
[Category:Errors reported by Module String].
no_category: If set to 'true' or 1, no category will be added if an error
is generated.
Unit tests for this module are available at Module:String/tests.
]]
local str = {}
--[[
len
This function returns the length of the target string.
Usage:
{{#invoke:String|len|target_string|}}
OR
{{#invoke:String|len|s=target_string}}
Parameters
s: The string whose length to report
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.
]]
function str.len( frame )
local new_args = str._getParameters( frame.args, {'s'} );
local s = new_args['s'] or '';
return mw.ustring.len( s )
end
--[[
sub
This function returns a substring of the target string at specified indices.
Usage:
{{#invoke:String|sub|target_string|start_index|end_index}}
OR
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}
Parameters
s: The string to return a subset of
i: The fist index of the substring to return, defaults to 1.
j: The last index of the string to return, defaults to the last character.
The first character of the string is assigned an index of 1. If either i or j
is a negative value, it is interpreted the same as selecting a character by
counting from the end of the string. Hence, a value of -1 is the same as
selecting the last character of the string.
If the requested indices are out of range for the given string, an error is
reported.
]]
function str.sub( frame )
local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } );
local s = new_args['s'] or '';
local i = tonumber( new_args['i'] ) or 1;
local j = tonumber( new_args['j'] ) or -1;
local len = mw.ustring.len( s );
-- Convert negatives for range checking
if i < 0 then
i = len + i + 1;
end
if j < 0 then
j = len + j + 1;
end
if i > len or j > len or i < 1 or j < 1 then
return str._error( '截取字符串索引脱离区间' );
end
if j < i then
return str._error( '截取字符串指示脱离顺序' );
end
return mw.ustring.sub( s, i, j )
end
--[[
This function implements that features of {{str sub old}} and is kept in order
to maintain these older templates.
]]
function str.sublength( frame )
local i = tonumber( frame.args.i ) or 0
local len = tonumber( frame.args.len )
return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )
end
--[[
match
This function returns a substring from the source string that matches a
specified pattern.
Usage:
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}
OR
{{#invoke:String|pos|s=source_string|pattern=pattern_string|start=start_index
|match=match_number|plain=plain_flag|nomatch=nomatch_output}}
Parameters
s: The string to search
pattern: The pattern or string to find within the string
start: The index within the source string to start the search. The first
character of the string has index 1. Defaults to 1.
match: In some cases it may be possible to make multiple matches on a single
string. This specifies which match to return, where the first match is
match= 1. If a negative number is specified then a match is returned
counting from the last match. Hence match = -1 is the same as requesting
the last match. Defaults to 1.
plain: A flag indicating that the pattern should be understood as plain
text. Defaults to false.
nomatch: If no match is found, output the "nomatch" value rather than an error.
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from each string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
If the match_number or start_index are out of range for the string being queried, then
this function generates an error. An error is also generated if no match is found.
If one adds the parameter ignore_errors=true, then the error will be suppressed and
an empty string will be returned on any failure.
For information on constructing Lua patterns, a form of [regular expression], see:
* http://www.lua.org/manual/5.1/manual.html#5.4.1
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns
]]
function str.match( frame )
local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} );
local s = new_args['s'] or '';
local start = tonumber( new_args['start'] ) or 1;
local plain_flag = str._getBoolean( new_args['plain'] or false );
local pattern = new_args['pattern'] or '';
local match_index = math.floor( tonumber(new_args['match']) or 1 );
local nomatch = new_args['nomatch'];
if s == '' then
return str._error( '目标字符串是空的' );
end
if pattern == '' then
return str._error( '模式字符串是空的' );
end
if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then
return str._error( '要求的起始点脱离区间' );
end
if match_index == 0 then
return str._error( '匹配索引脱离区间' );
end
if plain_flag then
pattern = str._escapePattern( pattern );
end
local result
if match_index == 1 then
-- Find first match is simple case
result = mw.ustring.match( s, pattern, start )
else
if start > 1 then
s = mw.ustring.sub( s, start );
end
local iterator = mw.ustring.gmatch(s, pattern);
if match_index > 0 then
-- Forward search
for w in iterator do
match_index = match_index - 1;
if match_index == 0 then
result = w;
break;
end
end
else
-- Reverse search
local result_table = {};
local count = 1;
for w in iterator do
result_table[count] = w;
count = count + 1;
end
result = result_table[ count + match_index ];
end
end
if result == nil then
if nomatch == nil then
return str._error( '找不到匹配' );
else
return nomatch;
end
else
return result;
end
end
--[[
pos
This function returns a single character from the target string at position pos.
Usage:
{{#invoke:String|pos|target_string|index_value}}
OR
{{#invoke:String|pos|target=target_string|pos=index_value}}
Parameters
target: The string to search
pos: The index for the character to return
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
The first character has an index value of 1.
If one requests a negative value, this function will select a character by counting backwards
from the end of the string. In other words pos = -1 is the same as asking for the last character.
A requested value of zero, or a value greater than the length of the string returns an error.
]]
function str.pos( frame )
local new_args = str._getParameters( frame.args, {'target', 'pos'} );
local target_str = new_args['target'] or '';
local pos = tonumber( new_args['pos'] ) or 0;
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
return str._error( '字符串索引脱离区间' );
end
return mw.ustring.sub( target_str, pos, pos );
end
--[[
str_find
This function duplicates the behavior of {{str_find}}, including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for
new code and templates. New code is recommended to use the "find" function instead.
Returns the first index in "source" that is a match to "target". Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".
Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.
]]
function str.str_find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target'} );
local source_str = new_args['source'] or '';
local target_str = new_args['target'] or '';
if target_str == '' then
return 1;
end
local start = mw.ustring.find( source_str, target_str, 1, true )
if start == nil then
start = -1
end
return start
end
--[[
find
This function allows one to search for a target string or pattern within another
string.
Usage:
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}
OR
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}
Parameters
source: The string to search
target: The string or pattern to find within source
start: The index within the source string to start the search, defaults to 1
plain: Boolean flag indicating that target should be understood as plain
text and not as a Lua style regular expression, defaults to true
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.
This function returns the first index >= "start" where "target" can be found
within "source". Indices are 1-based. If "target" is not found, then this
function returns 0. If either "source" or "target" are missing / empty, this
function also returns 0.
This function should be safe for UTF-8 strings.
]]
function str.find( frame )
local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['target'] or '';
local start_pos = tonumber(new_args['start']) or 1;
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return 0;
end
plain = str._getBoolean( plain );
local start = mw.ustring.find( source_str, pattern, start_pos, plain )
if start == nil then
start = 0
end
return start
end
--[[
replace
This function allows one to replace a target string or pattern within another
string.
Usage:
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}
OR
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|
count=replacement_count|plain=plain_flag}}
Parameters
source: The string to search
pattern: The string or pattern to find within source
replace: The replacement text
count: The number of occurences to replace, defaults to all.
plain: Boolean flag indicating that pattern should be understood as plain
text and not as a Lua style regular expression, defaults to true
]]
function str.replace( frame )
local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );
local source_str = new_args['source'] or '';
local pattern = new_args['pattern'] or '';
local replace = new_args['replace'] or '';
local count = tonumber( new_args['count'] );
local plain = new_args['plain'] or true;
if source_str == '' or pattern == '' then
return source_str;
end
plain = str._getBoolean( plain );
if plain then
pattern = str._escapePattern( pattern );
replace = mw.ustring.gsub( replace, "%%", "%%%%" ); --Only need to escape replacement sequences.
end
local result;
if count ~= nil then
result = mw.ustring.gsub( source_str, pattern, replace, count );
else
result = mw.ustring.gsub( source_str, pattern, replace );
end
return result;
end
--[[
simple function to pipe string.rep to templates.
]]
function str.rep( frame )
local repetitions = tonumber( frame.args[2] )
if not repetitions then
return str._error( 'function rep expects a number as second parameter, received "' .. ( frame.args[2] or '' ) .. '"' )
end
return string.rep( frame.args[1] or '', repetitions )
end
function str.split(inputstr, sep, no_pattern, ignore_null)
--#invoke 支援
if type(inputstr) == type({table}) then
if not getArgs then getArgs = require('Module:Arguments').getArgs end
args = getArgs(inputstr, {parentFirst=true})
for arg_name, arg_value in pairs( args ) do
if arg_name == 1 or arg_name == '1' or arg_name == "str" or arg_name == "inputstr" or arg_name == "input" then
input_str = arg_value
elseif arg_name == 2 or arg_name == '2' or arg_name == "sep" or arg_name == "separator" then
separ = arg_value
elseif arg_name == 3 or arg_name == '3' or arg_name == "no_pattern" or arg_name == "no pattern" then
no_pattern_flag = arg_value
elseif arg_name == 4 or arg_name == '4' or arg_name == "ignore_null" or arg_name == "ignore null" then
ignore_null_flag = arg_value
elseif arg_name == 5 or arg_name == '5' or arg_name == "format" then
format = arg_value or "*{{{1}}}\n";
end
end
if not yesno then yesno = require('Module:Yesno') end
no_pattern_flag = yesno( no_pattern_flag or 'yes' )
ignore_null_flag = yesno( ignore_null_flag or 'no' )
is_invoke = true
format = mw.ustring.gsub(format or "*{{{1}}}\n", "%{%{%{.-%}%}%}", "%%s" );
it = mw.ustring.find(format, "%%s", 1)
if it == nil then format = format .. "%s" end
format = mw.ustring.gsub(format, "\\n", "\n")
else
input_str = inputstr
separ = sep
no_pattern_flag = no_pattern
ignore_null_flag = ignore_null
is_invoke = false
end
input_str = input_str or ''
separ = separ or "%s"
if no_pattern_flag == nil then no_pattern_flag = true end
if ignore_null_flag == nil then ignore_null_flag = false end
length = mw.ustring.len(input_str)
--split函數起點
if no_pattern_flag then
separ = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(separ,
"%[", "%["), "%]", "%]"), "%{", "%{"), "%}", "%}"), "%%", "%%%%"), "%)", "%)"), "%-", "%-"),
"%^", "%^"), "%$", "%$"), "%(", "%("), "%.", "%."), "%*", "%*"), "%+", "%+"), "%|", "%|");
end
iterator = 1 ; i = 1 ; flag = true
result = {}
separ_str_begin, separ_str_end = mw.ustring.find(input_str, separ, iterator)
--
debug1 = 1
--
while flag do
debug1 = debug1 + 1
if separ_str_begin == nil or iterator > length or debug1 >= 100 then
separ_str_begin = 0
separ_str_end = -2
flag = false
end
if separ_str_end < separ_str_begin then separ_str_end = separ_str_begin end
finded_str = mw.ustring.sub(input_str, iterator, separ_str_begin - 1)
if not(mw.text.trim(finded_str) == '' and ignore_null_flag) then
result[i] = finded_str
i = i + 1
end
iterator = separ_str_end + 1
separ_str_begin, separ_str_end = mw.ustring.find(input_str, separ, iterator)
end
if is_invoke then
body = ''
for i, result_str in pairs( result ) do
body = body .. mw.ustring.gsub(format, "%%s", result_str)
end
return body
end
return result;
end
--[[
join
Join all non empty arguments together; the first argument is the separator.
Usage:
{{#invoke:String|join|sep|one|two|three}}
]]
function str.join(frame)
local args = {}
local sep
for _, v in ipairs( frame.args ) do
if sep then
if v ~= '' then
table.insert(args, v)
end
else
sep = v
end
end
return table.concat( args, sep or '' )
end
--[[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]]
function str._getParameters( frame_args, arg_list )
local new_args = {};
local index = 1;
local value;
for i,arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index];
index = index + 1;
end
new_args[arg] = value;
end
return new_args;
end
--[[
Helper function to handle error messages.
]]
function str._error( error_str )
local frame = mw.getCurrentFrame();
local error_category = frame.args.error_category or '字符串模块报告的错误';
local ignore_errors = frame.args.ignore_errors or false;
local no_category = frame.args.no_category or false;
if str._getBoolean(ignore_errors) then
return '';
end
local error_str = '<strong class="error">字符串模块出错:' .. error_str .. '</strong>';
if error_category ~= '' and not str._getBoolean( no_category ) then
error_str = '[[Category:' .. error_category .. ']]' .. error_str;
end
return error_str;
end
--[[
Helper Function to interpret boolean strings
]]
function str._getBoolean( boolean_str )
local boolean_value;
if type( boolean_str ) == 'string' then
boolean_str = boolean_str:lower();
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
or boolean_str == '' then
boolean_value = false;
else
boolean_value = true;
end
elseif type( boolean_str ) == 'boolean' then
boolean_value = boolean_str;
else
error( '布尔值找不到' );
end
return boolean_value
end
--[[
Helper function that escapes all pattern characters so that they will be treated
as plain text.
]]
function str._escapePattern( pattern_str )
return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end
return str
46d6ec0e303056a09a84a6da45fba79504276c7f
Module:Navbox
828
75
145
144
2024-08-02T10:51:23Z
黑茶
2
导入1个版本
Scribunto
text/plain
--
-- This module will implement {{Navbox}}
--
local p = {}
local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized
local args
local tableRowAdded = false
local border
local listnums = {}
local function trim(s)
return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end
local function addNewline(s)
if s:match('^[*:;#]') or s:match('^{|') then
return '\n' .. s ..'\n'
else
return s
end
end
local function addTableRow(tbl)
-- If any other rows have already been added, then we add a 2px gutter row.
if tableRowAdded then
tbl
:tag('tr')
:css('height', '2px')
:tag('td')
:attr('colspan', 3)
end
tableRowAdded = true
return tbl:tag('tr')
end
local function renderNavBar(titleCell)
-- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
-- or right to keep the title centered.
local spacerSide = nil
if args.navbar == 'off' then
-- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
-- also no show/hide link, then we need a spacer on the right to achieve the left shift.
if args.state == 'plain' then spacerSide = 'right' end
elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox' and (border == 'subgroup' or border == 'child' or border == 'none')) then
-- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
if args.state ~= 'plain' then spacerSide = 'left' end
else
-- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
-- to balance out the width of the navbar.
if args.state == 'plain' then spacerSide = 'right' end
titleCell:wikitext(navbar{
args.name,
mini = 1,
fontstyle = 'color:inherit;' .. (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;'
})
end
-- Render the spacer div.
if spacerSide then
titleCell
:tag('span')
:css('float', spacerSide)
:css('position', 'absolute')
:css(spacerSide, '1em')
:css('margin-' .. (spacerSide == 'left' and 'right' or 'left'), '0.5em')
:css('padding-' .. spacerSide, '0.2em')
:wikitext(' ')
end
end
--
-- Title row
--
local function renderTitleRow(tbl)
if not args.title then return end
local titleRow = addTableRow(tbl)
if args.titlegroup then
titleRow
:tag('th')
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.titlegroupclass)
:cssText(args.basestyle)
:cssText(args.groupstyle)
:cssText(args.titlegroupstyle)
:wikitext(args.titlegroup)
end
local titleCell = titleRow:tag('th'):attr('scope', 'col')
if args.titlegroup then
titleCell
:css('border-left', '2px solid #fdfdfd')
:css('width', '100%')
end
local titleColspan = 2
if args.imageleft then titleColspan = titleColspan + 1 end
if args.image then titleColspan = titleColspan + 1 end
if args.titlegroup then titleColspan = titleColspan - 1 end
titleCell
:cssText(args.basestyle)
:cssText(args.titlestyle)
:addClass('navbox-title')
:addClass(args.titleclass)
:attr('colspan', titleColspan)
renderNavBar(titleCell)
titleCell
:tag('div')
:css('font-size', '110%')
:wikitext(addNewline(args.title))
end
--
-- Above/Below rows
--
local function getAboveBelowColspan()
local ret = 2
if args.imageleft then ret = ret + 1 end
if args.image then ret = ret + 1 end
return ret
end
local function renderAboveRow(tbl)
if not args.above then return end
addTableRow(tbl)
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.aboveclass)
:cssText(args.basestyle)
:cssText(args.abovestyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(addNewline(args.above))
end
local function renderBelowRow(tbl)
if not args.below then return end
addTableRow(tbl)
:tag('td')
:addClass('navbox-abovebelow')
:addClass(args.belowclass)
:cssText(args.basestyle)
:cssText(args.belowstyle)
:attr('colspan', getAboveBelowColspan())
:tag('div')
:wikitext(addNewline(args.below))
end
--
-- List rows
--
local function renderListRow(tbl, listnum)
local row = addTableRow(tbl)
if listnum == 1 and args.imageleft then
row
:tag('td')
:addClass('navbox-image')
:addClass(args.imageclass)
:css('width', '0%')
:css('padding', '0px 2px 0px 0px')
:cssText(args.imageleftstyle)
:attr('rowspan', 2 * #listnums - 1)
:tag('div')
:wikitext(addNewline(args.imageleft))
end
if args['group' .. listnum] then
local groupCell = row:tag('th')
groupCell
:attr('scope', 'row')
:addClass('navbox-group')
:addClass(args.groupclass)
:cssText(args.basestyle)
if args.groupwidth then
groupCell:css('width', args.groupwidth)
end
groupCell
:cssText(args.groupstyle)
:cssText(args['group' .. listnum .. 'style'])
:wikitext(args['group' .. listnum])
end
local listCell = row:tag('td')
if args['group' .. listnum] then
listCell
:css('text-align', 'left')
:css('border-left-width', '2px')
:css('border-left-style', 'solid')
else
listCell:attr('colspan', 2)
end
if not args.groupwidth then
listCell:css('width', '100%')
end
local isOdd = (listnum % 2) == 1
local rowstyle = args.evenstyle
if isOdd then rowstyle = args.oddstyle end
local evenOdd
if args.evenodd == 'swap' then
if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
else
if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
end
listCell
:css('padding', '0px')
:cssText(args.liststyle)
:cssText(rowstyle)
:cssText(args['list' .. listnum .. 'style'])
:addClass('navbox-list')
:addClass('navbox-' .. evenOdd)
:addClass(args.listclass)
:tag('div')
:css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
:wikitext(addNewline(args['list' .. listnum]))
if listnum == 1 and args.image then
row
:tag('td')
:addClass('navbox-image')
:addClass(args.imageclass)
:css('width', '0%')
:css('padding', '0px 0px 0px 2px')
:cssText(args.imagestyle)
:attr('rowspan', 2 * #listnums - 1)
:tag('div')
:wikitext(addNewline(args.image))
end
end
--
-- Tracking categories
--
local function needsHorizontalLists()
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent', 'hlist hlist-pipe', 'hlist hlist-hyphen'}
for i, cls in ipairs(listClasses) do
if args.listclass == cls or args.bodyclass == cls then
return false
end
end
return true
end
local function hasBackgroundColors()
return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
end
local function argNameAndRealTitleAreDifferent()
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
if args.name ~= mw.title.getCurrentTitle().text then
return true
end
return false
end
local function getTrackingCategories()
local cats = {}
if needsHorizontalLists() then table.insert(cats, '没有使用水平列表的导航框') end
if hasBackgroundColors() then table.insert(cats, '使用背景颜色的导航框') end
if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name參數和實際不同的導航框') end
return cats
end
local function renderTrackingCategories(builder)
local title = mw.title.getCurrentTitle()
if title.namespace ~= 10 then return end -- not in template space
local subpage = title.subpageText
if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
for i, cat in ipairs(getTrackingCategories()) do
builder:wikitext('[[Category:' .. cat .. ']]')
end
end
--
-- Main navbox tables
--
local function renderMainTable()
local tbl = mw.html.create('table')
:attr('cellspacing', 0)
:addClass('nowraplinks')
:addClass(args.bodyclass)
if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
if args.state == 'collapsed' then args.state = 'mw-collapsed' end
tbl
:addClass('mw-collapsible')
:addClass(args.state or 'autocollapse')
end
tbl:css('border-spacing', 0)
if border == 'subgroup' or border == 'child' or border == 'none' then
tbl
:addClass('navbox-subgroup')
:cssText(args.bodystyle)
:cssText(args.style)
else -- regular navobx - bodystyle and style will be applied to the wrapper table
tbl
:addClass('navbox-inner')
:css('background', 'transparent')
:css('color', 'inherit')
end
tbl:cssText(args.innerstyle)
renderTitleRow(tbl)
renderAboveRow(tbl)
for i, listnum in ipairs(listnums) do
renderListRow(tbl, listnum)
end
renderBelowRow(tbl)
return tbl
end
function p._navbox(navboxArgs)
args = navboxArgs
for k, v in pairs(args) do
local listnum = ('' .. k):match('^list(%d+)$')
if listnum then table.insert(listnums, tonumber(listnum)) end
end
table.sort(listnums)
border = trim(args.border or args[1] or '')
-- render the main body of the navbox
local tbl = renderMainTable()
-- render the appropriate wrapper around the navbox, depending on the border param
local res = mw.html.create()
if border == 'none' then
res:node(tbl)
elseif border == 'subgroup' or border == 'child' then
-- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
-- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
-- padding being applied, and at the end add a <div> to balance out the parent's </div>
res
:wikitext('</div>') -- mw.html 未支持 unclosed
:node(tbl)
:wikitext('<div>') -- mw.html 未支持 unclosed
else
res
:tag('table')
:attr('cellspacing', 0)
:addClass('navbox')
:css('border-spacing', 0)
:cssText(args.bodystyle)
:cssText(args.style)
:tag('tr')
:tag('td')
:css('padding', '2px')
:node(tbl)
end
renderTrackingCategories(res)
return tostring(res)
end
function p.navbox(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
args = getArgs(frame, {wrappers = 'Template:Navbox'})
-- Read the arguments in the order they'll be output in, to make references number in the right order.
local _
_ = args.title
_ = args.above
for i = 1, 35 do
_ = args["group" .. tostring(i)]
_ = args["list" .. tostring(i)]
end
_ = args.below
return p._navbox(args)
end
return p
6864182981324b61a13042fc742049007401dfa4
Module:Hatnote
828
76
147
146
2024-08-02T10:51:23Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote --
-- --
-- This module produces hatnote links and links to related articles. It --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules. --
--------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getArgs(frame)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
-- blanks are removed.
mArguments = require('Module:Arguments')
return mArguments.getArgs(frame, {parentOnly = true})
end
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
function p.findNamespaceId(link, removeColon)
-- Finds the namespace id (namespace number) of a link or a pagename. This
-- function will not work if the link is enclosed in double brackets. Colons
-- are trimmed from the start of the link by default. To skip colon
-- trimming, set the removeColon parameter to false.
checkType('findNamespaceId', 1, link, 'string')
checkType('findNamespaceId', 2, removeColon, 'boolean', true)
if removeColon ~= false then
link = removeInitialColon(link)
end
local namespace = link:match('^(.-):')
if namespace then
local nsTable = mw.site.namespaces[namespace]
if nsTable then
return nsTable.id
end
end
return 0
end
function p.formatPages(...)
-- Formats a list of pages using formatLink and returns it as an array. Nil
-- values are not allowed.
local pages = {...}
local ret = {}
for i, page in ipairs(pages) do
ret[i] = p._formatLink(page)
end
return ret
end
function p.formatPageTables(...)
-- Takes a list of page/display tables and returns it as a list of
-- formatted links. Nil values are not allowed.
local pages = {...}
local links = {}
for i, t in ipairs(pages) do
checkType('formatPageTables', i, t, 'table')
local link = t[1]
local display = t[2]
links[i] = p._formatLink(link, display)
end
return links
end
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
-- is added.
checkType('makeWikitextError', 1, msg, 'string')
checkType('makeWikitextError', 2, helpLink, 'string', true)
yesno = require('Module:Yesno')
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
local helpText
if helpLink then
helpText = '([[' .. helpLink .. '|帮助]])'
else
helpText = ''
end
-- Make the category text.
local category
if not title.isTalkPage and yesno(addTrackingCategory) ~= false then
category = '有错误的顶注模板'
category = string.format(
'[[%s:%s]]',
mw.site.namespaces[14].name,
category
)
else
category = ''
end
return string.format(
'<strong class="error">错误:%s%s。</strong>%s',
msg,
helpText,
category
)
end
function p.disambiguate(page, disambiguator)
-- Formats a page title with a disambiguation parenthetical,
-- i.e. "Example" → "Example (disambiguation)".
checkType('disambiguate', 1, page, 'string')
checkType('disambiguate', 2, disambiguator, 'string', true)
disambiguator = disambiguator or '消歧义'
return string.format('%s (%s)', page, disambiguator)
end
--------------------------------------------------------------------------------
-- Format link 格式化链接
--
-- Makes a wikilink from the given link and display values. Links are escaped
-- with colons if necessary, and links to sections are detected and displayed
-- with " § " as a separator rather than the standard MediaWiki "#". Used in
-- the {{format hatnote link}} template.
--------------------------------------------------------------------------------
function p.formatLink(frame)
local args = getArgs(frame)
local link = args[1]
local display = args[2]
if not link then
return p.makeWikitextError(
'link参数缺失',
'Template:Format hatnote link#错误',
args.category
)
end
return p._formatLink(link, display)
end
function p._formatLink(link, display)
checkType('_formatLink', 1, link, 'string')
checkType('_formatLink', 2, display, 'string', true)
-- ignore transwiki link
if link:match('<span class="ilh-') then
return link
end
-- Remove the initial colon for links where it was specified manually.
link = removeInitialColon(link)
-- Find whether a faux display value has been added with the {{!}} magic
-- word.
if not display then
local prePipe, postPipe = link:match('^(.-)|(.*)$')
link = prePipe or link
display = postPipe
end
-- Find the display value.
if not display then
local page, section = link:match('^(.-)#(.*)$')
if page then
display = page .. ' § ' .. section
end
end
-- Assemble the link.
if display then
return string.format(
'[[:%s|%s]]',
string.gsub(link, '|(.*)$', ''), --display overwrites manual piping
display
)
else
return string.format('[[:%s]]', link)
end
end
--------------------------------------------------------------------------------
-- Hatnote 顶注
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
-- 产生标准顶注文字。实现{{hatnote}}模板
--------------------------------------------------------------------------------
function p.hatnote(frame)
local args = getArgs(frame)
local s = args[1]
local options = {}
if not s then
return p.makeWikitextError(
'text参数缺失',
'Template:Hatnote#错误',
args.category
)
end
options.extraclasses = args.extraclasses
options.selfref = args.selfref
return p._hatnote(s, options)
end
function p._hatnote(s, options)
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 2, options, 'table', true)
options = options or {}
local classes = {'hatnote', 'navigation-not-searchable'}
local extraclasses = options.extraclasses
local selfref = options.selfref
if type(extraclasses) == 'string' then
classes[#classes + 1] = extraclasses
end
if selfref then
classes[#classes + 1] = 'selfref'
end
return string.format(
'<div role="note" class="%s">%s</div>',
table.concat(classes, ' '),
s
)
end
return p
adada2183763348aa1d17e8e24a47b05f39eb28c
Template:Tlc
10
77
149
148
2024-08-02T10:51:24Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<code style="white-space:nowrap;">-{}-{{{{#if:{{{1|}}}|{{{1}}}|tlc|...}}<!--
-->{{#ifeq:{{{2|x}}}|{{{2|}}}| |{{{2}}} | }}<!--
-->{{#ifeq:{{{3|x}}}|{{{3|}}}| |{{{3}}} | }}<!--
-->{{#ifeq:{{{4|x}}}|{{{4|}}}| |{{{4}}} | }}<!--
-->{{#ifeq:{{{5|x}}}|{{{5|}}}| |{{{5}}} | }}<!--
-->{{#ifeq:{{{6|x}}}|{{{6|}}}| |{{{6}}} | }}<!--
-->{{#ifeq:{{{7|x}}}|{{{7|}}}| |{{{7}}} | }}<!--
-->{{#ifeq:{{{8|x}}}|{{{8|}}}| |{{{8}}} | }}<!--
-->{{#ifeq:{{{9|x}}}|{{{9|}}}| |{{{9}}} | }}<!--
-->}}</code><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
db08bcc30fc73d9872756d0cde1c147fbfa4250a
Module:Navbar
828
78
151
150
2024-08-02T10:51:24Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
local cfg = mw.loadData('Module:Navbar/configuration')
local function get_title_arg(is_collapsible, template)
local title_arg = 1
if is_collapsible then title_arg = 2 end
if template then title_arg = 'template' end
return title_arg
end
local function choose_links(template, args)
-- The show table indicates the default displayed items.
-- view, talk, edit, hist, move, watch
-- TODO: Move to configuration.
local show = {true, true, true, false, false, false}
if template then
show[2] = false
show[3] = false
local index = {t = 2, d = 2, e = 3, h = 4, m = 5, w = 6,
talk = 2, edit = 3, hist = 4, move = 5, watch = 6}
-- TODO: Consider removing TableTools dependency.
for _, v in ipairs(require ('Module:TableTools').compressSparseArray(args)) do
local num = index[v]
if num then show[num] = true end
end
end
local remove_edit_link = args.noedit
if remove_edit_link then show[3] = false end
return show
end
local function add_link(link_description, ul, is_mini, font_style)
local l
if link_description.url then
l = {'[', '', ']'}
else
l = {'[[', '|', ']]'}
end
ul:tag('li')
:addClass('nv-' .. link_description.full)
:wikitext(l[1] .. link_description.link .. l[2])
:tag(is_mini and 'abbr' or 'span')
:attr('title', link_description.html_title)
:cssText(font_style)
:wikitext(is_mini and link_description.mini or link_description.full)
:done()
:wikitext(l[3])
:done()
end
local function make_list(title_text, has_brackets, displayed_links, is_mini, font_style)
local title = mw.title.new(mw.text.trim(title_text), cfg.title_namespace)
if not title then
error(cfg.invalid_title .. title_text)
end
local talkpage = title.talkPageTitle and title.talkPageTitle.fullText or ''
-- TODO: Get link_descriptions and show into the configuration module.
-- link_descriptions should be easier...
local link_descriptions = {
{ ['mini'] = '-{zh-hans:查;zh-hant:閱;}-', ['full'] = '-{zh-hans:查看;zh-hant:檢視;}-', ['html_title'] = '-{zh-hans:查看;zh-hant:檢視;}-该模板',
['link'] = title.fullText, ['url'] = false },
{ ['mini'] = '论', ['full'] = '讨论', ['html_title'] = '讨论该模板',
['link'] = talkpage, ['url'] = false },
{ ['mini'] = '编', ['full'] = '编辑', ['html_title'] = '编辑该模板',
['link'] = 'Special:EditPage/' .. title.fullText, ['url'] = false },
{ ['mini'] = '史', ['full'] = '历史', ['html_title'] = '该模板的历史',
['link'] = 'Special:PageHistory/' .. title.fullText, ['url'] = false },
{ ['mini'] = '移', ['full'] = '移动', ['html_title'] = '移动该模板',
['link'] = mw.title.new('Special:Movepage'):fullUrl('target='..title.fullText), ['url'] = true },
{ ['mini'] = '监', ['full'] = '监视', ['html_title'] = '监视该模板',
['link'] = title:fullUrl('action=watch'), ['url'] = true }
}
local ul = mw.html.create('ul')
if has_brackets then
ul:addClass(cfg.classes.brackets)
:cssText(font_style)
end
for i, _ in ipairs(displayed_links) do
if displayed_links[i] then add_link(link_descriptions[i], ul, is_mini, font_style) end
end
return ul:done()
end
function p._navbar(args)
-- TODO: We probably don't need both fontstyle and fontcolor...
local font_style = args.fontstyle
local font_color = args.fontcolor
local is_collapsible = args.collapsible
local is_mini = args.mini
local is_plain = args.plain
local collapsible_class = nil
if is_collapsible then
collapsible_class = cfg.classes.collapsible
if not is_plain then is_mini = 1 end
if font_color then
font_style = (font_style or '') .. '; color: ' .. font_color .. ';'
end
end
local navbar_style = args.style
local div = mw.html.create():tag('div')
div
:addClass(cfg.classes.navbar)
:addClass(cfg.classes.plainlinks)
:addClass(cfg.classes.horizontal_list)
:addClass(collapsible_class) -- we made the determination earlier
:cssText(navbar_style)
if is_mini then div:addClass(cfg.classes.mini) end
local box_text = (args.text or cfg.box_text) .. ''
-- the concatenated space guarantees the box text is separated
if not (is_mini or is_plain) then
div
:tag('span')
:addClass(cfg.classes.box_text)
:cssText(font_style)
:wikitext(box_text)
end
local template = args.template
local displayed_links = choose_links(template, args)
local has_brackets = args.brackets
local title_arg = get_title_arg(is_collapsible, template)
local title_text = args[title_arg] or (':' .. mw.getCurrentFrame():getParent():getTitle())
local list = make_list(title_text, has_brackets, displayed_links, is_mini, font_style)
div:node(list)
if is_collapsible then
local title_text_class
if is_mini then
title_text_class = cfg.classes.collapsible_title_mini
else
title_text_class = cfg.classes.collapsible_title_full
end
div:done()
:tag('div')
:addClass(title_text_class)
:cssText(font_style)
:wikitext(args[1])
end
local frame = mw.getCurrentFrame()
-- hlist -> navbar is best-effort to preserve old Common.css ordering.
return frame:extensionTag{
name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
} .. frame:extensionTag{
name = 'templatestyles', args = { src = cfg.templatestyles }
} .. tostring(div:done())
end
function p.navbar(frame)
return p._navbar(require('Module:Arguments').getArgs(frame))
end
return p
ea41e2eba702ca65d1f599ce2fe7ce148a30b192
Template:Para
10
79
153
152
2024-08-02T10:51:24Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<code lang="en" class="nowrap">|{{#if:{{{1|}}}|{{{1}}}=}}{{{2|}}}</code><noinclude>
{{Documentation}}
[[Category:輸入支援模板]]
[[Category:格式模板]]
<!--Categories and interwikis go near the bottom of the /doc subpage.-->
</noinclude>
5299c3a8d06166c23855a3461733c7cc4698830d
Module:Hatnote list
828
80
155
154
2024-08-02T10:51:25Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Hatnote list --
-- --
-- This module produces and formats lists for use in hatnotes. In particular, --
-- it implements the for-see list, i.e. lists of "For X, see Y" statements, --
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced --
-- are andList & orList helpers for formatting lists with those conjunctions. --
--------------------------------------------------------------------------------
local mArguments --initialize lazily
local mHatnote = require('Module:Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
--------------------------------------------------------------------------------
-- List stringification helper functions
--
-- These functions are used for stringifying lists, usually page lists inside
-- the "Y" portion of "For X, see Y" for-see items.
--------------------------------------------------------------------------------
--default options table used across the list stringification functions
-- 本地化注意
local stringifyListDefaultOptions = {
conjunction = "和",
separator = "、",
altSeparator = ";",
space = "",
formatted = false,
boldfaced = false,
quotes = false
}
-- Stringifies a list generically; probably shouldn't be used directly
function stringifyList(list, options)
-- Type-checks, defaults, and a shortcut
checkType("stringifyList", 1, list, "table")
if #list == 0 then return nil end
checkType("stringifyList", 2, options, "table", true)
options = options or {}
for k, v in pairs(stringifyListDefaultOptions) do
if options[k] == nil then options[k] = v end
end
local s = options.space
-- Format the list if requested
if options.formatted then list = mHatnote.formatPages(unpack(list)) end
-- Set the separator; if any item contains it, use the alternate separator
local separator = options.separator
--searches display text only
function searchDisp(t, f)
return string.find(string.sub(t, (string.find(t, '|') or 0) + 1), f)
end
for k, v in pairs(list) do
-- 本地化注意
if options.boldfaced then
list[k] = '\'\'\'' .. list[k] .. '\'\'\''
end
if options.quotes then
list[k] = '「' .. list[k] .. '」'
end
if searchDisp(v, separator) then
separator = options.altSeparator
break
end
end
-- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§"
local conjunction = s .. options.conjunction .. s
-- 本地化注意
-- separator .. conjunction的结果是“、和”
-- if #list == 2 and searchDisp(list[1], "§") or #list > 2 then
-- conjunction = separator .. conjunction
-- end
-- Return the formatted string
return mw.text.listToText(list, separator .. s, conjunction)
end
--DRY function
-- 本地化注意
function conjList (conj, list, fmt, bold, quo)
return stringifyList(list, {conjunction = conj, formatted = fmt, boldfaced = bold, quotes=quo})
end
-- Stringifies lists with "and" or "or"
-- 本地化注意
function p.andList (...) return conjList("和", ...) end
function p.orList (...) return conjList("或", ...) end
--------------------------------------------------------------------------------
-- For see
--
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the
-- {{about}} and {{redirect}} templates and their variants.
--------------------------------------------------------------------------------
--default options table used across the forSee family of functions
-- 本地化注意
local forSeeDefaultOptions = {
andKeyword = '和',
title = mw.title.getCurrentTitle().text,
otherText = '其他用法',
forSeeForm = '关于%s,请见%s。',
}
--Collapses duplicate punctuation
-- 本地化注意
function punctuationCollapse (text)
local replacements = {
["%.%.$"] = ".",
["%?%.$"] = "?",
["%!%.$"] = "!",
["%.%]%]%.$"] = ".]]",
["%?%]%]%.$"] = "?]]",
["%!%]%]%.$"] = "!]]",
["%。%。$"] = "。",
["%?%。$"] = "?",
["%!%。$"] = "!",
["%。%]%]%。$"] = "。]]",
["%?%]%]%。$"] = "?]]",
["%!%]%]%。$"] = "!]]"
}
for k, v in pairs(replacements) do text = string.gsub(text, k, v) end
return text
end
-- Structures arguments into a table for stringification, & options
function p.forSeeArgsToTable (args, from, options)
-- Type-checks and defaults
checkType("forSeeArgsToTable", 1, args, 'table')
checkType("forSeeArgsToTable", 2, from, 'number', true)
from = from or 1
checkType("forSeeArgsToTable", 3, options, 'table', true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- maxArg's gotten manually because getArgs() and table.maxn aren't friends
local maxArg = 0
for k, v in pairs(args) do
if type(k) == 'number' and k > maxArg then maxArg = k end
end
-- Structure the data out from the parameter list:
-- * forTable is the wrapper table, with forRow rows
-- * Rows are tables of a "use" string & a "pages" table of pagename strings
-- * Blanks are left empty for defaulting elsewhere, but can terminate list
local forTable = {}
local i = from
local terminated = false
-- If there is extra text, and no arguments are given, give nil value
-- to not produce default of "For other uses, see foo (disambiguation)"
if options.extratext and i > maxArg then return nil end
-- Loop to generate rows
repeat
-- New empty row
local forRow = {}
-- On blank use, assume list's ended & break at end of this loop
forRow.use = args[i]
if not args[i] then terminated = true end
-- New empty list of pages
forRow.pages = {}
-- Insert first pages item if present
table.insert(forRow.pages, args[i + 1])
-- If the param after next is "and", do inner loop to collect params
-- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3}
while args[i + 2] == options.andKeyword do
if args[i + 3] then
table.insert(forRow.pages, args[i + 3])
end
-- Increment to next "and"
i = i + 2
end
-- Increment to next use
i = i + 2
-- Append the row
table.insert(forTable, forRow)
until terminated or i > maxArg
return forTable
end
-- Stringifies a table as formatted by forSeeArgsToTable
function p.forSeeTableToString (forSeeTable, options)
-- Type-checks and defaults
checkType("forSeeTableToString", 1, forSeeTable, "table", true)
checkType("forSeeTableToString", 2, options, "table", true)
options = options or {}
for k, v in pairs(forSeeDefaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Stringify each for-see item into a list
local strList = {}
if forSeeTable then
for k, v in pairs(forSeeTable) do
local useStr = v.use or options.otherText
-- 本地化注意
local pagesStr = p.andList(v.pages, true, true, true) or '「\'\'\'' .. mHatnote._formatLink(mHatnote.disambiguate(options.title)) .. '\'\'\'」'
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)
forSeeStr = punctuationCollapse(forSeeStr)
table.insert(strList, forSeeStr)
end
end
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'。')) end
-- Return the concatenated list
return table.concat(strList)
end
-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps
-- but not blank/whitespace values. Ignores named args and args < "from".
function p._forSee (args, from, options)
local forSeeTable = p.forSeeArgsToTable(args, from, options)
return p.forSeeTableToString(forSeeTable, options)
end
-- As _forSee, but uses the frame.
function p.forSee (frame, from, options)
mArguments = require('Module:Arguments')
return p._forSee(mArguments.getArgs(frame), from, options)
end
return p
38feee2afbc1ce641c952305addbbea4f726544a
Template:Tl
10
81
157
156
2024-08-02T10:51:25Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{[[{{transclude|{{{1}}}}}|{{{1}}}]]{{#if:{{{2|{{{arg|}}}}}}|{{!}}{{{2|{{{arg}}}}}}}}}}</includeonly><noinclude>
{{Documentation}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
db73d4542a3c4808bbcbc2708c654b3bc0834fba
Template:Transclude
10
82
159
158
2024-08-02T10:51:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch: {{NAMESPACE: {{{1}}} }}
|#default = {{FULLPAGENAME: {{{1}}} }} <!-- eg "User:Foo" -->
|{{ns:0}} =
{{#ifeq: {{NAMESPACE: {{{1}}} }} | {{NAMESPACE: Template{{{1}}} }}
| Template:{{{1}}} <!-- no leading colon, eg "Foo" -->
| {{PAGENAME: {{{1}}} }} <!-- leading colon, eg ":Foo", so we want the article -->
}}
}}<noinclude>
{{documentation}}
</noinclude>
d0239e71e5745cd0d4efd032cee07341e111376b
Module:Pagetype
828
83
161
160
2024-08-02T10:51:26Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- --
-- PAGETYPE --
-- --
-- This is a meta-module intended to replace {{pagetype}} and similar --
-- templates. It automatically detects namespaces, and allows for a --
-- great deal of customisation. It can easily be ported to other --
-- wikis by changing the values in the [[Module:Pagetype/config]]. --
-- --
--------------------------------------------------------------------------------
-- Load config.
local cfg = mw.loadData('Module:Pagetype/config')
-- Load required modules.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local nsDetectModule = require('Module:Namespace detect')
local nsDetect = nsDetectModule._main
local getParamMappings = nsDetectModule.getParamMappings
local getPageObject = nsDetectModule.getPageObject
local p = {}
local function shallowCopy(t)
-- Makes a shallow copy of a table.
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
local function checkPagetypeInput(namespace, val)
-- Checks to see whether we need the default value for the given namespace,
-- and if so gets it from the pagetypes table.
-- The yesno function returns true/false for "yes", "no", etc., and returns
-- val for other input.
local ret = yesno(val, val)
if ret and type(ret) ~= 'string' then
ret = cfg.pagetypes[namespace]
end
return ret
end
local function getPagetypeFromClass(class, param, aliasTable, default)
-- Gets the pagetype from a class specified from the first positional
-- parameter.
param = yesno(param, param)
if param ~= false then -- No check if specifically disallowed.
for _, alias in ipairs(aliasTable) do
if class == alias then
if type(param) == 'string' then
return param
else
return default
end
end
end
end
end
local function getNsDetectValue(args)
-- Builds the arguments to pass to [[Module:Namespace detect]] and returns
-- the result.
-- Get the default values.
local ndArgs = {}
local defaultns = args[cfg.defaultns]
if defaultns == cfg.defaultnsAll then
ndArgs = shallowCopy(cfg.pagetypes)
else
local defaultnsArray
if defaultns == cfg.defaultnsExtended then
defaultnsArray = cfg.extendedNamespaces
elseif defaultns == cfg.defaultnsNone then
defaultnsArray = {}
else
defaultnsArray = cfg.defaultNamespaces
end
for _, namespace in ipairs(defaultnsArray) do
ndArgs[namespace] = cfg.pagetypes[namespace]
end
end
--[[
-- Add custom values passed in from the arguments. These overwrite the
-- defaults. The possible argument names are fetched from
-- Module:Namespace detect automatically in case new namespaces are
-- added. Although we accept namespace aliases as parameters, we only pass
-- the local namespace name as a parameter to Module:Namespace detect.
-- This means that the "image" parameter can overwrite defaults for the
-- File: namespace, which wouldn't work if we passed the parameters through
-- separately.
--]]
local mappings = getParamMappings()
for ns, paramAliases in pairs(mappings) do
-- Copy the aliases table, as # doesn't work with tables returned from
-- mw.loadData.
paramAliases = shallowCopy(paramAliases)
local paramName = paramAliases[1]
-- Iterate backwards along the array so that any values for the local
-- namespace names overwrite those for namespace aliases.
for i = #paramAliases, 1, -1 do
local paramAlias = paramAliases[i]
local ndArg = checkPagetypeInput(paramAlias, args[paramAlias])
if ndArg == false then
-- If any arguments are false, convert them to nil to protect
-- against breakage by future changes to
-- [[Module:Namespace detect]].
ndArgs[paramName] = nil
elseif ndArg then
ndArgs[paramName] = ndArg
end
end
end
-- Check for disambiguation-class and N/A-class pages in mainspace.
if ndArgs.main then
local class = args[1]
if type(class) == 'string' then
-- Put in lower case so e.g. "Dab" and "dab" will both match.
class = mw.ustring.lower(class)
end
local dab = getPagetypeFromClass(
class,
args[cfg.dab],
cfg.dabAliases,
cfg.dabDefault
)
if dab then
ndArgs.main = dab
else
local na = getPagetypeFromClass(
class,
args[cfg.na],
cfg.naAliases,
cfg.naDefault
)
if na then
ndArgs.main = na
end
end
end
-- If there is no talk value specified, use the corresponding subject
-- namespace for talk pages.
if not ndArgs.talk then
ndArgs.subjectns = true
end
-- Add the fallback value. This can also be customised, but it cannot be
-- disabled.
local other = args[cfg.other]
-- We will ignore true/false/nil results from yesno here, but using it
-- anyway for consistency.
other = yesno(other, other)
if type(other) == 'string' then
ndArgs.other = other
else
ndArgs.other = cfg.otherDefault
end
-- Allow custom page values.
ndArgs.page = args.page
return nsDetect(ndArgs)
end
local function detectRedirects(args)
local redirect = args[cfg.redirect]
-- The yesno function returns true/false for "yes", "no", etc., and returns
-- redirect for other input.
redirect = yesno(redirect, redirect)
if redirect == false then
-- Detect redirects unless they have been explicitly disallowed with
-- "redirect=no" or similar.
return
end
local pageObject = getPageObject(args.page)
-- If we are using subject namespaces elsewhere, do so here as well.
if pageObject
and not yesno(args.talk, true)
and args[cfg.defaultns] ~= cfg.defaultnsAll
then
pageObject = getPageObject(
pageObject.subjectNsText .. ':' .. pageObject.text
)
end
-- Allow custom values for redirects.
if pageObject and pageObject.isRedirect then
if type(redirect) == 'string' then
return redirect
else
return cfg.redirectDefault
end
end
end
function p._main(args)
local redirect = detectRedirects(args)
if redirect then
return redirect
else
return getNsDetectValue(args)
end
end
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
return p
4e76ed8318e724693304c0ca2063b36b0890825a
Module:Pagetype/config
828
84
163
162
2024-08-02T10:51:27Z
黑茶
2
导入1个版本
Scribunto
text/plain
--------------------------------------------------------------------------------
-- Module:Pagetype configuration data --
-- This page holds localisation and configuration data for Module:Pagetype. --
--------------------------------------------------------------------------------
local cfg = {} -- Don't edit this line.
--------------------------------------------------------------------------------
-- Start configuration data --
--------------------------------------------------------------------------------
-- This table holds the values to use for "main=true", "user=true", etc. Keys to
-- this table should be namespace parameters that can be used with
-- [[Module:Namespace detect]].
cfg.pagetypes = {
['main'] = '條目',
['user'] = '用戶頁',
['project'] = '維基百科',
['wikipedia'] = '維基百科',
['wp'] = '維基百科',
['file'] = '-{zh-cn:文件; zh-tw:檔案;}-',
['image'] = '-{zh-cn:文件; zh-tw:檔案;}-',
['mediawiki'] = 'MediaWiki',
['template'] = '模板',
['help'] = '幫助',
['category'] = '分類',
['portal'] = '主題',
['wikiproject'] = '維基專題',
['wpj'] = '維基專題',
['pj'] = '維基專題',
['book'] = '圖書',
['draft'] = '草稿',
['education program'] = '教育課程',
['timedtext'] = '字幕',
['module'] = '-{zh-cn:模块; zh-tw:模組;}-',
['topic'] = '話題',
['talk'] = '討論頁',
['special'] = '特殊頁面',
['media'] = '檔案'
}
-- This table holds the names of the namespaces to be looked up from
-- cfg.pagetypes by default.
cfg.defaultNamespaces = {
'main',
'file',
'template',
'category',
'module',
'book'
}
-- This table holds the names of the namespaces to be looked up from
-- cfg.pagetypes if cfg.defaultnsExtended is set.
cfg.extendedNamespaces = {
'main',
'user',
'project',
'file',
'mediawiki',
'template',
'category',
'help',
'portal',
'wikiproject',
'module',
'book',
'draft'
}
-- The parameter name to set which default namespace values to be looked up from
-- cfg.pagetypes.
cfg.defaultns = 'defaultns'
-- The value of cfg.defaultns to set all namespaces, including talk.
cfg.defaultnsAll = 'all'
-- The value of cfg.defaultns to set the namespaces listed in
-- cfg.extendedNamespaces
cfg.defaultnsExtended = 'extended'
-- The value of cfg.defaultns to set no default namespaces.
cfg.defaultnsNone = 'none'
-- The parameter name to use for disambiguation pages page.
cfg.dab = 'dab'
-- This table holds the different possible aliases for disambiguation-class
-- pages. These should be lower-case.
cfg.dabAliases = {
'disambiguation',
'disambig',
'disamb',
'dab',
'消歧义',
'消歧義'
}
-- The default value for disambiguation pages.
cfg.dabDefault = '页面'
-- The parameter name to use for N/A-class page.
cfg.na = 'na'
-- This table holds the different possible aliases for N/A-class pages. These
-- should be lower-case.
cfg.naAliases = {'na', 'n/a','非条目','非條目'}
-- The default value for N/A-class pages.
cfg.naDefault = '页面'
-- The parameter name to use for redirects.
cfg.redirect = 'redirect'
-- The default value to use for redirects.
cfg.redirectDefault = '重定向'
-- The parameter name for undefined namespaces.
cfg.other = 'other'
-- The value used if the module detects an undefined namespace.
cfg.otherDefault = '页面'
--------------------------------------------------------------------------------
-- End configuration data --
--------------------------------------------------------------------------------
return cfg -- Don't edit this line
7336d20d10f77b58f24be9386797b4823179bf7c
Module:Namespace detect
828
85
165
164
2024-08-02T10:51:27Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[
--------------------------------------------------------------------------------
-- --
-- NAMESPACE DETECT --
-- --
-- This module implements the {{namespace detect}} template in Lua, with a --
-- few improvements: all namespaces and all namespace aliases are supported, --
-- and namespace names are detected automatically for the local wiki. The --
-- module can also use the corresponding subject namespace value if it is --
-- used on a talk page. Parameter names can be configured for different wikis --
-- by altering the values in the "cfg" table in --
-- Module:Namespace detect/config. --
-- --
--------------------------------------------------------------------------------
--]]
local data = mw.loadData('Module:Namespace detect/data')
local argKeys = data.argKeys
local cfg = data.cfg
local mappings = data.mappings
local yesno = require('Module:Yesno')
local mArguments -- Lazily initialise Module:Arguments
local mTableTools -- Lazily initilalise Module:TableTools
local ustringLower = mw.ustring.lower
local p = {}
local function fetchValue(t1, t2)
-- Fetches a value from the table t1 for the first key in array t2 where
-- a non-nil value of t1 exists.
for i, key in ipairs(t2) do
local value = t1[key]
if value ~= nil then
return value
end
end
return nil
end
local function equalsArrayValue(t, value)
-- Returns true if value equals a value in the array t. Otherwise
-- returns false.
for i, arrayValue in ipairs(t) do
if value == arrayValue then
return true
end
end
return false
end
function p.getPageObject(page)
-- Get the page object, passing the function through pcall in case of
-- errors, e.g. being over the expensive function count limit.
if page then
local success, pageObject = pcall(mw.title.new, page)
if success then
return pageObject
else
return nil
end
else
return mw.title.getCurrentTitle()
end
end
-- Provided for backward compatibility with other modules
function p.getParamMappings()
return mappings
end
local function getNamespace(args)
-- This function gets the namespace name from the page object.
local page = fetchValue(args, argKeys.demopage)
if page == '' then
page = nil
end
local demospace = fetchValue(args, argKeys.demospace)
if demospace == '' then
demospace = nil
end
local subjectns = fetchValue(args, argKeys.subjectns)
local ret
if demospace then
-- Handle "demospace = main" properly.
if equalsArrayValue(argKeys.main, ustringLower(demospace)) then
ret = mw.site.namespaces[0].name
else
ret = demospace
end
else
local pageObject = p.getPageObject(page)
if pageObject then
if pageObject.isTalkPage then
-- Get the subject namespace if the option is set,
-- otherwise use "talk".
if yesno(subjectns) then
ret = mw.site.namespaces[pageObject.namespace].subject.name
else
ret = 'talk'
end
else
ret = pageObject.nsText
end
else
return nil -- return nil if the page object doesn't exist.
end
end
ret = ret:gsub('_', ' ')
return ustringLower(ret)
end
function p._main(args)
-- Check the parameters stored in the mappings table for any matches.
local namespace = getNamespace(args) or 'other' -- "other" avoids nil table keys
local params = mappings[namespace] or {}
local ret = fetchValue(args, params)
--[[
-- If there were no matches, return parameters for other namespaces.
-- This happens if there was no text specified for the namespace that
-- was detected or if the demospace parameter is not a valid
-- namespace. Note that the parameter for the detected namespace must be
-- completely absent for this to happen, not merely blank.
--]]
if ret == nil then
ret = fetchValue(args, argKeys.other)
end
return ret
end
function p.main(frame)
mArguments = require('Module:Arguments')
local args = mArguments.getArgs(frame, {removeBlanks = false})
local ret = p._main(args)
return ret or ''
end
function p.table(frame)
--[[
-- Create a wikitable of all subject namespace parameters, for
-- documentation purposes. The talk parameter is optional, in case it
-- needs to be excluded in the documentation.
--]]
-- Load modules and initialise variables.
mTableTools = require('Module:TableTools')
local namespaces = mw.site.namespaces
local cfg = data.cfg
local useTalk = type(frame) == 'table'
and type(frame.args) == 'table'
and yesno(frame.args.talk) -- Whether to use the talk parameter.
-- Get the header names.
local function checkValue(value, default)
if type(value) == 'string' then
return value
else
return default
end
end
local nsHeader = checkValue(cfg.wikitableNamespaceHeader, 'Namespace')
local aliasesHeader = checkValue(cfg.wikitableAliasesHeader, 'Aliases')
-- Put the namespaces in order.
local mappingsOrdered = {}
for nsname, params in pairs(mappings) do
if useTalk or nsname ~= 'talk' then
local nsid = namespaces[nsname].id
-- Add 1, as the array must start with 1; nsid 0 would be lost otherwise.
nsid = nsid + 1
mappingsOrdered[nsid] = params
end
end
mappingsOrdered = mTableTools.compressSparseArray(mappingsOrdered)
-- Build the table.
local ret = '{| class="wikitable"'
.. '\n|-'
.. '\n! ' .. nsHeader
.. '\n! ' .. aliasesHeader
for i, params in ipairs(mappingsOrdered) do
for j, param in ipairs(params) do
if j == 1 then
ret = ret .. '\n|-'
.. '\n| <code>' .. param .. '</code>'
.. '\n| '
elseif j == 2 then
ret = ret .. '<code>' .. param .. '</code>'
else
ret = ret .. ', <code>' .. param .. '</code>'
end
end
end
ret = ret .. '\n|-'
.. '\n|}'
return ret
end
return p
a4757000273064f151f0f22dc0e139092e5ff443
Module:List
828
86
167
166
2024-08-02T10:51:27Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module outputs different kinds of lists. At the moment, bulleted,
-- unbulleted, horizontal, ordered, and horizontal ordered lists are supported.
local libUtil = require('libraryUtil')
local checkType = libUtil.checkType
local mTableTools = require('Module:TableTools')
local p = {}
local listTypes = {
['bulleted'] = true,
['unbulleted'] = true,
['horizontal'] = true,
['ordered'] = true,
['horizontal_ordered'] = true
}
function p.makeListData(listType, args)
-- Constructs a data table to be passed to p.renderList.
local data = {}
-- Classes
data.classes = {}
if listType == 'horizontal' or listType == 'horizontal_ordered' then
table.insert(data.classes, 'hlist')
elseif listType == 'unbulleted' then
table.insert(data.classes, 'plainlist')
end
table.insert(data.classes, args.class)
-- Main div style
data.style = args.style
-- Indent for horizontal lists
if listType == 'horizontal' or listType == 'horizontal_ordered' then
local indent = tonumber(args.indent)
indent = indent and indent * 1.6 or 0
if indent > 0 then
data.marginLeft = indent .. 'em'
end
end
-- List style types for ordered lists
-- This could be "1, 2, 3", "a, b, c", or a number of others. The list style
-- type is either set by the "type" attribute or the "list-style-type" CSS
-- property.
if listType == 'ordered' or listType == 'horizontal_ordered' then
data.listStyleType = args.list_style_type or args['list-style-type']
data.type = args['type']
-- Detect invalid type attributes and attempt to convert them to
-- list-style-type CSS properties.
if data.type
and not data.listStyleType
and not tostring(data.type):find('^%s*[1AaIi]%s*$')
then
data.listStyleType = data.type
data.type = nil
end
end
-- List tag type
if listType == 'ordered' or listType == 'horizontal_ordered' then
data.listTag = 'ol'
else
data.listTag = 'ul'
end
-- Start number for ordered lists
data.start = args.start
if listType == 'horizontal_ordered' then
-- Apply fix to get start numbers working with horizontal ordered lists.
local startNum = tonumber(data.start)
if startNum then
data.counterReset = 'listitem ' .. tostring(startNum - 1)
end
end
-- List style
-- ul_style and ol_style are included for backwards compatibility. No
-- distinction is made for ordered or unordered lists.
data.listStyle = args.list_style
-- List items
-- li_style is included for backwards compatibility. item_style was included
-- to be easier to understand for non-coders.
data.itemStyle = args.item_style or args.li_style
data.items = {}
for i, num in ipairs(mTableTools.numKeys(args)) do
local item = {}
item.content = args[num]
item.style = args['item' .. tostring(num) .. '_style']
or args['item_style' .. tostring(num)]
or args['li_style' .. tostring(num)]
item.value = args['item' .. tostring(num) .. '_value']
or args['item_value' .. tostring(num)]
or args['li_value' .. tostring(num)]
table.insert(data.items, item)
end
return data
end
function p.renderList(data)
-- Renders the list HTML.
-- Return the blank string if there are no list items.
if type(data.items) ~= 'table' or #data.items < 1 then
return ''
end
-- Render the main div tag.
local root = mw.html.create('div')
for i, class in ipairs(data.classes or {}) do
root:addClass(class)
end
root:css{['margin-left'] = data.marginLeft}
if data.style then
root:cssText(data.style)
end
-- Render the list tag.
local list = root:tag(data.listTag or 'ul')
list
:attr{start = data.start, type = data.type}
:css{
['counter-reset'] = data.counterReset,
['list-style-type'] = data.listStyleType
}
if data.listStyle then
list:cssText(data.listStyle)
end
-- Render the list items
for i, t in ipairs(data.items or {}) do
local item = list:tag('li')
if data.itemStyle then
item:cssText(data.itemStyle)
end
if t.style then
item:cssText(t.style)
end
item
:attr{value = t.value}
:wikitext(t.content)
end
return tostring(root)
end
function p.renderTrackingCategories(args)
local isDeprecated = false -- Tracks deprecated parameters.
for k, v in pairs(args) do
k = tostring(k)
if k:find('^item_style%d+$') or k:find('^item_value%d+$') then
isDeprecated = true
break
end
end
local ret = ''
if isDeprecated then
ret = ret .. '[[Category:含有过期参数的列表模板]]'
end
return ret
end
function p.makeList(listType, args)
if not listType or not listTypes[listType] then
error(string.format(
"bad argument #1 to 'makeList' ('%s'不是合适的列表类型)",
tostring(listType)
), 2)
end
checkType('makeList', 2, args, 'table')
local data = p.makeListData(listType, args)
local list = p.renderList(data)
local trackingCategories = p.renderTrackingCategories(args)
return list .. trackingCategories
end
for listType in pairs(listTypes) do
p[listType] = function (frame)
local mArguments = require('Module:Arguments')
local origArgs = mArguments.getArgs(frame)
-- Copy all the arguments to a new table, for faster indexing.
local args = {}
for k, v in pairs(origArgs) do
args[k] = v
end
return p.makeList(listType, args)
end
end
return p
4199cf5283d8a457f8e13ce703726cb8ea84a08b
Template:Icon
10
87
169
168
2024-08-02T10:51:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:Icon|main}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
bd5b855953c5eec9d9c48400aa39315cb4218558
Module:Icon
828
88
171
170
2024-08-02T10:51:28Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements [[Template:Icon]].
local data = mw.loadData('Module:Icon/data')
local p = {}
function p._main(args)
local code = args.class or args[1]
local iconData
if code then
code = code:match('^%s*(.-)%s*$'):lower() -- trim whitespace and put in lower case
iconData = data[code]
end
if not iconData then
iconData = data._DEFAULT
end
return string.format(
'[[File:%s%s|%s|link=]]',
iconData.image,
iconData.tooltip and '|' .. iconData.tooltip or '',
args.size or '16x16px'
)
end
function p.main(frame)
local args = {}
for k, v in pairs(frame:getParent().args) do
args[k] = v
end
return p._main(args)
end
return p
2a9d51e44f8cd64c8eeb17655d5238da36908650
Module:Icon/data
828
89
173
172
2024-08-02T10:51:29Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module stores icon data for [[Module:Icon]].
--------------------------------------------------------------------------------
-- Icon data
--------------------------------------------------------------------------------
local data = {
fa = {
image = "Featured article star.svg",
tooltip = "典范条目",
},
far = {
image = "Cscr-star piece.png",
tooltip = "典范条目候选",
},
farc = {
image = "Cscr-star piece.png",
tooltip = "典范条目重审",
},
ffa = {
aliases = {"dfa"},
image = "Featured article star - cross.svg",
tooltip = "已被撤销的典范条目",
},
fac = {
aliases = {"fan"},
image = "Cscr-candidate.svg",
tooltip = "典范条目评选",
},
ffac = {
aliases = {"nofa"},
image = "Featured article star - cross.svg",
tooltip = "落选典范条目",
},
fl = {
image = "Featured article star.svg",
tooltip = "特色列表",
},
flrc = {
aliases = {"flr"},
image = "Cscr-star piece.png",
tooltip = "特色列表重审",
},
ffl = {
aliases = {"dfl"},
image = "Cscr-featured-strike.svg",
tooltip = "已被撤销的特色列表",
},
flc = {
aliases = {"fln"},
image = "Cscr-candidate.svg",
tooltip = "特色列表候选",
},
fflc = {
aliases = {"nofl"},
image = "Featured article star - cross.svg",
tooltip = "落选特色列表",
},
a = {
image = "Symbol a class.svg",
tooltip = "甲级条目",
},
dac = {
aliases = {"daa"},
image = "Symbol unsupport A vote.svg",
tooltip = "已降级甲级条目",
},
acc = {
aliases = {"acn", "aac"},
image = "A candidate.svg",
tooltip = "甲级条目候选",
},
noac = {
aliases = {"faac"},
image = "Symbol unsupport A vote.svg",
tooltip = "落选甲级条目",
},
ga = {
image = "Symbol support vote.svg",
tooltip = "优良条目",
},
gar = {
image = "GA Candidate Neutral vote(ChaosNil).svg",
tooltip = "优良条目重审",
},
dga = {
image = "Symbol unsupport vote.svg",
tooltip = "已被撤销的优良条目",
},
gan = {
aliases = {"gac"},
image = "GA candidate.svg",
tooltip = "优良条目候选",
},
ga2 = {
image = "Symbol neutral vote.svg",
tooltip = "寻求意见的优良条目",
},
gah = {
image = "Symbol wait.svg",
tooltip = "搁置的优良条目",
},
fgan = {
aliases = {"noga", "gaf", "gf"},
image = "Symbol oppose vote.svg",
tooltip = "落选优良条目",
},
fp = {
image = "Cscr-featured.svg",
tooltip = "特色图片",
},
fpc = {
aliases = {"fpn"},
image = "Cscr-candidate.svg",
tooltip = "特色图片候选",
},
ffpc = {
aliases = {"nofp"},
image = "Featured article star - cross.svg",
tooltip = "落选特色图片",
},
ffp = {
image = "Featured article star - cross.svg",
tooltip = "已被撤销的特色图片",
},
vp = {
image = "ENWP VP Logo.svg",
tooltip = "珍贵图片",
},
vpc = {
image = "Valued pics 1.svg",
tooltip = "珍贵图片候选",
},
fs = {
image = "Cscr-featured.svg",
tooltip = "特色声音",
},
ffs = {
image = "Cscr-former.svg",
tooltip = "已被撤销的特色声音",
},
fsc = {
image = "Cscr-candidate.svg",
tooltip = "特色声音候选",
},
fpo = {
image = "Cscr-featured.svg",
tooltip = "特色主题",
},
fpor = {
image = "Cscr-star piece.png",
tooltip = "特色主题评选",
},
ffpo = {
image = "Featured article star - cross.svg",
tooltip = "已被撤销的特色主题",
},
fpoc = {
image = "Cscr-candidate.svg",
tooltip = "特色主题候选",
},
ft = {
image = "Cscr-featuredtopic.svg",
tooltip = "特色话题",
},
ftrc = {
image = "Cscr-star piece.png",
tooltip = "特色话题重审",
},
fft = {
aliases = {"dft"},
image = "DFT candidate_cluster.svg",
tooltip = "已被撤销的特色话题",
},
ftc = {
aliases = {"ftn"},
image = "FT candidate cluster.svg",
tooltip = "特色话题候选",
},
gt = {
image = "Support cluster.svg",
tooltip = "优良话题",
},
gtrc = {
image = "Symbol unsupport vote.svg",
tooltip = "优良话题重审",
},
gtc = {
aliases = {"gtn"},
image = "GA candidate cluster.svg",
tooltip = "优良话题候选",
},
bplus = {
aliases = {"b+"},
image = "Symbol bplus class.svg",
tooltip = "乙+级条目",
},
b = {
image = "Symbol b class.svg",
tooltip = "乙级条目",
},
br = {
aliases = {"bcr"},
image = "Bclass-checklist.svg",
tooltip = "乙级条目评选",
},
c = {
image = "Symbol c class.svg",
tooltip = "丙级条目",
},
start = {
image = "Symbol start class.svg",
tooltip = "初级条目",
},
stub = {
image = "Symbol stub class.svg",
tooltip = "小作品级条目",
},
list = {
aliases = {"comparison"},
image = "Symbol list class.svg",
tooltip = "列表级条目",
},
no = {
image = "Crystal button cancel.svg",
tooltip = "未知分级条目",
},
book = {
image = "Symbol book class2.svg",
tooltip = "维基百科图书",
},
category = {
aliases = {"cat", "categ"},
image = "Symbol category class.svg",
tooltip = "分类",
},
disambiguation = {
aliases = {"dab", "disamb", "disambig"},
image = "Symbol dab class.svg",
tooltip = "消歧义页",
},
image = {
aliases = {"file"},
image = "Video-x-generic.svg",
tooltip = "文件",
},
portal = {
image = "Symbol portal class.svg",
tooltip = "主题",
},
project = {
image = "Symbol information vote.svg",
tooltip = "项目页面",
},
redirect = {
aliases = {"red", "redir"},
image = "Symbol redirect vote2.svg",
tooltip = "重定向页",
},
template = {
aliases = {"temp", "templ"},
image = "Symbol template class.svg",
tooltip = "模板",
},
essay = {
image = "Essay.svg",
tooltip = "论述",
},
na = {
image = "Symbol neutral vote.svg",
tooltip = "非条目页面",
},
aa = {
image = "Yes check.svg",
tooltip = "限定主题的已审条目",
},
da = {
image = "Symbol oppose vote.svg",
tooltip = "降级条目",
},
dyk = {
image = "Symbol question.svg",
tooltip = "你知道吗?",
},
dyk2 = {
image = "DYK questionmark icon.svg",
tooltip = "你知道吗?",
},
dykc = {
aliases = {"dykn"},
image = "DYK candidate.svg",
tooltip = "你知道吗?候选",
},
pr = {
image = "Nuvola apps kedit.png",
tooltip = "同行评审",
},
ppr = {
image = "Nuvola apps kedit.png",
tooltip = "主题同行评审",
},
q = {
aliases = {"question"},
image = "Symbol question.svg",
tooltip = "问题",
},
qi = {
image = "Quality images logo.svg",
tooltip = "维基共享资源优质图像",
},
vi = {
image = "Valued image seal.svg",
tooltip = "维基共享资源珍贵图像",
},
tfa = {
image = "Wikipedia-logo.svg",
tooltip = "今日典范条目",
},
itn = {
image = "Globe current.svg",
tooltip = "新闻动态",
},
otd = {
image = "Nuvola apps date.svg",
tooltip = "历史上的今天",
},
wikiproject = {
image = "People icon.svg",
tooltip = "专题",
},
wikipedia = {
image = "Wikipedia-logo.svg",
tooltip = "维基百科页面",
},
commons = {
image = "Commons-logo.svg",
tooltip = "共享资源页面",
},
wikiquote = {
image = "Wikiquote-logo.svg",
tooltip = "维基语录页面",
},
wikiversity = {
image = "Wikiversity-logo.svg",
tooltip = "维基学院页面",
},
wikibooks = {
image = "Wikibooks-logo.svg",
tooltip = "维基教科书页面",
},
wikisource = {
image = "Wikisource-logo.svg",
tooltip = "维基文库页面",
},
wiktionary = {
image = "Wiktionary-logo.svg",
tooltip = "维基词典页面",
},
wikinews = {
image = "Wikinews-logo.svg",
tooltip = "维基新闻页面",
},
wikispecies = {
image = "Wikispecies-logo.svg",
tooltip = "维基物种页面",
},
wikidata = {
image = "Wikidata-logo.svg",
tooltip = "维基数据页面",
},
wikivoyage = {
image = "Wikivoyage-logo.svg",
tooltip = "维基导游页面",
},
meta = {
image = "Wikimedia Community Logo.svg",
tooltip = "元维基页面",
},
four = {
image = "Four Award.svg",
tooltip = "Four Award",
},
million = {
image = "Million award logo.svg",
tooltip = "Million Award",
},
dc = {
aliases = {"DC"},
image = "Wikipedia_zh_dc_logo.svg",
tooltip = "维基百科动员令",
},
wam = {
aliases = {"WAM"},
image = "WAM_logo_without_text.svg",
tooltip = "维基百科亚洲月",
},
wafm = {
aliases = {"WAFM"},
image = "African_Month_Medal.svg",
tooltip = "维基百科非洲月",
},
-- WP:VA usage
vaa = {
image = "Yes check.svg",
tooltip = "> 30 KB",
},
vab = {
image = "Yes check lines.svg",
tooltip = "10 - 30 KB",
},
vac = {
image = "QSicon in Arbeit.svg",
tooltip = "3 - 10 KB",
},
_DEFAULT = {
image = "Symbol question.svg",
}
}
--------------------------------------------------------------------------------
-- End icon data
--------------------------------------------------------------------------------
-- Make aliases work the same as normal keys, and remove the "aliases" subtables.
for k, t in pairs(data) do
if t.aliases then
for i, alias in ipairs(t.aliases) do
data[alias] = t
end
t.aliases = nil
end
data[k] = t
end
return data
b388921315ecd10da77ae36a0172274d23560d2c
Template:Hlist/styles.css
10
90
175
174
2024-08-02T10:51:29Z
黑茶
2
导入1个版本
sanitized-css
text/css
.hlist ul,
.hlist ol {
padding-left: 0;
}
/* reset hlist margins of Minerva */
.hlist li,
.hlist dd,
.hlist dt {
margin: 0;
display: inline;
}
.hlist dt:after,
.hlist dd:after,
.hlist li:after {
white-space: normal;
}
/* Generate interpuncts */
.hlist dt:after {
content: " :";
}
.hlist dd:after,
.hlist li:after {
content: " · ";
font-weight: bold;
}
.hlist-pipe dd:after,
.hlist-pipe li:after {
content: " | ";
font-weight: normal;
}
.hlist-hyphen dd:after,
.hlist-hyphen li:after {
content: " - ";
font-weight: normal;
}
.hlist-comma dd:after,
.hlist-comma li:after {
content: "、";
font-weight: normal;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist dd:last-child:after,
.hlist dt:last-child:after,
.hlist li:last-child:after {
content: none;
}
/* Put ordinals in front of ordered list items */
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol {
counter-reset: listitem;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol > li {
counter-increment: listitem;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist ol > li:before {
content: " " counter(listitem) " ";
white-space: nowrap;
}
/* Should be removed and moved to templates once TemplateStyles is live */
.hlist dd ol > li:first-child:before,
.hlist dt ol > li:first-child:before,
.hlist li ol > li:first-child:before {
content: " (" counter(listitem) " ";
}
/* Put ordinals in front of ordered list items */
.hlist ol {
counter-reset: listitem;
}
.hlist ol > li {
counter-increment: listitem;
}
.hlist ol > li:before {
content: " " counter(listitem) "\a0";
}
.hlist dd ol > li:first-child:before,
.hlist dt ol > li:first-child:before,
.hlist li ol > li:first-child:before {
content: " (" counter(listitem) "\a0";
}
/* make an inline list with either comma or semicolon separators */
ul.cslist, ul.sslist {
margin: 0;
padding: 0;
display: inline-block;
list-style: none;
}
.cslist li, .sslist li {
margin: 0;
display: inline-block;
}
.cslist li:after {
content: ",";
}
.sslist li:after {
content: ";";
}
.cslist li:last-child:after, .sslist li:last-child:after {
content: none;
}
1cdc0ded2a44e617938a2368d34995a74727972a
Template:Namespace pagename
10
91
177
176
2024-08-02T10:51:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{{{{|safesubst:}}}If subst
| 1 = {{Namespace pagename{{{{{|safesubst:}}}#if:{{{1|}}}|{{{{{|safesubst:}}}!}}1{{{{{|safesubst:}}}=}}{{{1}}}}}{{{{{|safesubst:}}}#if:{{{2|}}}|{{{{{|safesubst:}}}!}}2{{{{{|safesubst:}}}=}}{{{2}}}}}}}
| 2 = <!--
-->{{#switch:<!--
---->{{#ifeq:{{{2|Empty}}}<!--
---->| Empty<!--
---->| {{ns:{{NAMESPACENUMBER}}}}<!-- If there is no input in {{{2}}}, then {{NAMESPACENUMBER}} will be returned.
---->| <!--
------>{{#if:{{#invoke:Page|isExternal|{{{2}}}}}<!--
------>| External<!--
------>| <!--
-------->{{#ifeq:{{{2}}}<!--
-------->| {{PAGENAME:{{{2}}}}}<!--
-------->| <!--
---------->{{#if:{{PAGENAME:{{ns:{{{2}}}}}}}<!--
---------->| {{ns:{{{2}}}}}<!--
---------->| <!--
------------>{{#switch:{{{2}}}<!--
------------>| MOS = MOS<!-- If {{{2}}} equals MOS, then MOS will be returned.
------------>| LTA = LTA<!-- If {{{2}}} equals LTA, then LTA will be returned.
------------>| NT = NT<!-- If {{{2}}} equals NT, then NT will be returned.
------------>| NC = NC<!-- If {{{2}}} equals NC, then NC will be returned.
------------>| #default = {{ns:0}}<!-- If there is no prefix in {{{2}}}, then {{ns:0}} will be returned.
------------>}}<!--
---------->}}<!--
-------->| {{NAMESPACE:{{{2}}}}}<!-- If {{{2}}} equals {{FULLPAGENAME}}, then {{NAMESPACE}} will be returned.
-------->}}<!--
------>}}<!--
---->}}<!--
-->| External = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 跨语言链接<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 跨語言連結<!--
---->| #default = Interlanguage link<!--
---->}}<!--
-->| MOS = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊捷徑<!--
---->| #default = Manual of Style<!--
---->}}<!--
-->| LTA = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者捷徑<!--
---->| #default = Long-term abuse<!--
---->}}<!--
-->| NT = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引捷徑<!--
---->| #default = Notability Guidelines<!--
---->}}<!--
-->| NC = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规快捷方式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規捷徑<!--
---->| #default = Naming Conventions<!--
---->}}<!--
-->| {{ns:-2}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 媒体<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 媒體<!--
---->| #default = Media<!--
---->}}<!--
-->| {{ns:-1}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 特殊<!--
---->| #default = Special<!--
---->}}<!--
-->| {{ns:0}} = <!--
---->{{#switch:<!--
------>{{Str mid<!--
------>| {{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}<!--
------>| <!--
------>| {{#expr:abs({{str find|{{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}|:}})-1}}<!--
------>}}<!--
---->| MOS = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊捷徑<!--
------>| #default = Manual of Style<!--
------>}}<!--
---->| LTA = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者捷徑<!--
------>| #default = Long-term abuse<!--
------>}}<!--
---->| NT = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引捷徑<!--
------>| #default = Notability Guidelines<!--
------>}}<!--
---->| NC = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規捷徑<!--
------>| #default = Naming Conventions<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 条目<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 條目<!--
------>| #default = Article<!--
------>}}<!--
---->}}<!--
-->| {{ns:1}} = <!--
---->{{#switch:<!--
------>{{Str mid<!--
------>| {{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}<!--
------>| 6<!--
------>| {{#expr:abs({{Str find|{{str mid|{{FULLPAGENAME:{{{2|{{FULLPAGENAME}}}}}}}|6}}|:}})-1}}<!--
------>}}<!--
---->| MOS = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 格式手册讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 格式手冊討論捷徑<!--
------>| #default = Manual of Style talk<!--
------>}}<!--
---->| LTA = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 持续出没的破坏者讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 持續出沒的破壞者討論捷徑<!--
------>| #default = Long-term abuse talk<!--
------>}}<!--
---->| NT = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 关注度指引讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 關注度指引討論捷徑<!--
------>| #default = Notability Guidelines talk<!--
------>}}<!--
---->| NC = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 命名常规讨论快捷方式<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 命名常規討論捷徑<!--
------>| #default = Naming Conventions talk<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 讨论<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 討論<!--
------>| #default = Talk<!--
------>}}<!--
---->}}<!--
-->| {{ns:2}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 用户<!--
---->| zh-hant | zh-hk | zh-mo = 用戶<!--
---->| zh-tw = 使用者<!--
---->| #default = User<!--
---->}}<!--
-->| {{ns:3}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 用户讨论<!--
---->| zh-hant | zh-hk | zh-mo = 用戶討論<!--
---->| zh-tw = 使用者討論<!--
---->| #default = User talk<!--
---->}}<!--
-->| {{ns:4}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 项目<!--
---->| zh-hant | zh-hk | zh-mo = 專案<!--
---->| zh-tw = 計畫<!--
---->| #default = Project<!--
---->}}<!--
-->| {{ns:5}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 项目讨论<!--
---->| zh-hant | zh-hk | zh-mo = 專案討論<!--
---->| zh-tw = 計畫討論<!--
---->| #default = Project talk<!--
---->}}<!--
-->| {{ns:6}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文件<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 檔案<!--
---->| #default = File<!--
---->}}<!--
-->| {{ns:7}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文件讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 檔案討論<!--
---->| #default = File talk<!--
---->}}<!--
-->| {{ns:8}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 界面<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 介面<!--
---->| #default = MediaWiki<!--
---->}}<!--
-->| {{ns:9}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 界面讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 介面討論<!--
---->| #default = MediaWiki talk<!--
---->}}<!--
-->| {{ns:10}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 模板<!--
---->| #default = Template<!--
---->}}<!--
-->| {{ns:11}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模板讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模板討論<!--
---->| #default = Template talk<!--
---->}}<!--
-->| {{ns:12}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 帮助<!--
---->| zh-hant | zh-hk | zh-mo = 幫助<!--
---->| zh-tw = 使用說明<!--
---->| #default = Help<!--
---->}}<!--
-->| {{ns:13}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 帮助讨论<!--
---->| zh-hant | zh-hk | zh-mo = 幫助討論<!--
---->| zh-tw = 使用說明討論<!--
---->| #default = Help talk<!--
---->}}<!--
-->| {{ns:14}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 分类<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 分類<!--
---->| #default = Category<!--
---->}}<!--
-->| {{ns:15}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 分类讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 分類討論<!--
---->| #default = Category talk<!--
---->}}<!--
-->| {{ns:100}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 主题<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 主題<!--
---->| #default = Portal<!--
---->}}<!--
-->| {{ns:101}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 主题讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 主題討論<!--
---->| #default = Portal talk<!--
---->}}<!--
-->| {{ns:102}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 维基专题<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 維基專題<!--
---->| #default = WikiProject<!--
---->}}<!--
-->| {{ns:103}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 维基专题讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 維基專題討論<!--
---->| #default = WikiProject talk<!--
---->}}<!--
-->| {{ns:118}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 草稿<!--
---->| #default = Draft<!--
---->}}<!--
-->| {{ns:119}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 草稿讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 草稿討論<!--
---->| #default = Draft talk<!--
---->}}<!--
-->| {{ns:710}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 字幕<!--
---->| #default = TimedText<!--
---->}}<!--
-->| {{ns:711}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 字幕讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 字幕討論<!--
---->| #default = TimedText talk<!--
---->}}<!--
-->| {{ns:828}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模块<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模組<!--
---->| #default = Module<!--
---->}}<!--
-->| {{ns:829}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 模块讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 模組討論<!--
---->| #default = Module talk<!--
---->}}<!--
-->| {{ns:2600}} = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 结构式讨论<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 結構式討論<!--
---->| #default = Structured discussions<!--
---->}}<!--
-->| #default = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = {{Error|命名空间侦测错误。}}<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = {{Error|命名空間偵測錯誤。}}<!--
---->| #default = {{Error|There's an error in the detection of namespace.}}<!--
---->}}<!--
-->}}<!--
-->{{#switch:{{#invoke:Page|contentModel|{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{{2}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}}}<!--
-->| css | sanitized-css = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 样式<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 樣式<!--
---->| #default = styles<!--
---->}}<!--
-->| javascript = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 脚本<!--
---->| zh-hant | zh-tw | zh-hk | zh-mo = 工具<!--
---->| #default = scripts<!--
---->}}<!--
-->| json = <!--
---->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
---->| zh-hans | zh-cn | zh-sg | zh-my | zh = 数据<!--
---->| zh-hant | zh-hk | zh-mo = 數據<!--
---->| zh-tw = 資料<!--
---->| #default = data<!--
---->}}<!--
-->| #default = <!--
---->{{#switch:<!--
------>{{#if:{{{2|}}}<!--
------>| <!--
-------->{{#ifeq:{{{2}}}<!--
-------->| {{PAGENAME:{{{2}}}}}<!--
-------->| <!--
-------->| <!--
---------->{{#if:{{#ifeq:{{{}}}|R|{{#invoke:Page|isRedirect|{{{2}}}}}}}<!--
---------->| Redirect<!--
---------->| <!--
------------>{{If in page<!--
------------>| page = {{{2}}}<!--
------------>| %{%{[Dd]ocumentation[_%s]subpage<!--
------------>| doc<!--
------------>| <!--
-------------->{{If in page<!--
-------------->| page = {{{2}}}<!--
-------------->| %{%{[Tt]emplate[_%s]doc[_%s]page[_%s]viewed[_%s]directly<!--
-------------->| doc<!--
-------------->| <!--
---------------->{{If in page<!--
---------------->| page = {{{2}}}<!--
---------------->| %{%{[Ss]andbox<!--
---------------->| sandbox<!--
---------------->| <!--
------------------>{{If in page<!--
------------------>| page = {{{2}}}<!--
------------------>| %{%{[Ss]andbox[_%s]heading<!--
------------------>| sandbox<!--
------------------>| <!--
-------------------->{{If in page<!--
-------------------->| page = {{{2}}}<!--
-------------------->| %{%{请注意:请在这行文字底下进行您的测试,请不要删除或变更这行文字以及这行文字以上的部分。<!--
-------------------->| sandbox<!--
-------------------->| <!--
---------------------->{{If in page<!--
---------------------->| page = {{{2}}}<!--
---------------------->| %{%{請注意:請在這行文字底下進行您的測試,請不要刪除或變更這行文字以及這行文字以上的部份。<!--
---------------------->| sandbox<!--
---------------------->| <!--
------------------------>{{If in page<!--
------------------------>| page = {{{2}}}<!--
------------------------>| %{%{[Tt]emplate[_%s]sandbox[_%s]notice<!--
------------------------>| sandbox<!--
------------------------>| <!--
-------------------------->{{If in page<!--
-------------------------->| page = {{{2}}}<!--
-------------------------->| %{%{[Tt]estcases[_%s]notice<!--
-------------------------->| testcases<!--
-------------------------->| <!--
---------------------------->{{If in page<!--
---------------------------->| page = {{{2}}}<!--
---------------------------->| %{%{[Tt]emplate[_%s]test[_%s]cases[_%s]notice<!--
---------------------------->| testcases|<!--
------------------------------>{{If in page<!--
------------------------------>| page = {{{2}}}<!--
------------------------------>| %{%{测试样例<!--
------------------------------>| testcases<!--
------------------------------>| <!--
-------------------------------->{{If in page<!--
-------------------------------->| page = {{{2}}}<!--
-------------------------------->| %{%{測試樣例<!--
-------------------------------->| testcases<!--
-------------------------------->| {{SUBPAGENAME:{{Str right|{{{2}}}|5}}}}<!--
-------------------------------->}}<!--
------------------------------>}}<!--
---------------------------->}}<!--
-------------------------->}}<!--
------------------------>}}<!--
---------------------->}}<!--
-------------------->}}<!--
------------------>}}<!--
---------------->}}<!--
-------------->}}<!--
------------>}}<!--
---------->}}<!--
-------->}}<!--
------>| {{SUBPAGENAME}}<!--
------>}}<!--
---->| Redirect = <!--
------>{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
------>| zh-hans | zh-cn | zh-sg | zh-my | zh = 重定向<!--
------>| zh-hant | zh-tw | zh-hk | zh-mo = 重新導向<!--
------>| #default = redirect<!--
------>}}<!--
---->| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 文档<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 文件<!--
-------->| #default = documentation<!--
-------->}}<!--
------>}}<!--
---->| sandbox | Sandbox | 沙盒 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh-hant | zh-tw | zh-hk | zh-mo = 沙盒<!--
-------->| #default = sandbox<!--
-------->}}<!--
------>}}<!--
---->| testcases | Testcases | 测试样例 | 測試樣例 = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:0}} | {{ns:6}} | {{ns:7}} | {{ns:14}} | {{ns:15}} | {{ns:118}} | {{ns:119}} | {{ns:2600}} = <!--
------>| #default = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 测试样例<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 測試樣例<!--
-------->| #default = testcases<!--
-------->}}<!--
------>}}<!--
---->| #default = <!--
------>{{#switch:{{#if:{{{2|}}}|{{#ifeq:{{{2}}}|{{PAGENAME:{{{2}}}}}||{{NAMESPACE:{{{2}}}}}}}|{{ns:{{NAMESPACENUMBER}}}}}}<!--
------>| {{ns:1}} | {{ns:3}} | {{ns:4}} | {{ns:5}} | {{ns:7}} | {{ns:8}} | {{ns:9}} | {{ns:11}} | {{ns:12}} | {{ns:13}} | {{ns:15}} | {{ns:101}} | {{ns:103}} | {{ns:119}} | {{ns:829}} | {{ns:2301}} | {{ns:2302}} | {{ns:2303}} | {{ns:2600}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 頁<!--
-------->| #default = page<!--
-------->}}<!--
------>| {{ns:-2}} | {{ns:-1}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页面<!--
-------->| zh-hant | zh-tw | zh-hk | zh-mo = 頁面<!--
-------->| #default = page<!--
-------->}}<!--
------>| {{ns:2}} = <!--
-------->{{#switch:{{#switch:{{lc:{{{1|}}}}}||zh={{int:Conversionname}}|#default={{{1}}}}}<!--
-------->| zh-hans | zh-cn | zh-sg | zh-my | zh = 页<!--
-------->| zh-hant | zh-hk | zh-mo = 頁<!--
-------->| zh-tw = 頁面<!--
-------->| #default = page<!--
-------->}}<!--
------>}}<!--
---->}}<!--
-->}}
}}<noinclude>
{{Documentation}}</noinclude>
18c73d7accdd7e8b2f9f30db4a9721a43dbdd799
Template:If subst
10
92
179
178
2024-08-02T10:51:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#Redirect [[Template:Ifsubst]]
{{Redirect category shell|
{{模板重定向}}
}}
cab6ab798c451f05c48bff4c9c8d0e7174badb78
Template:Ifsubst
10
93
181
180
2024-08-02T10:51:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{ {{{|safesubst:}}}#ifeq:{{ {{{|safesubst:}}}NAMESPACE}}{{{nosubst|}}}|{{NAMESPACE}}
|{{{no|{{{2|}}}}}}
|{{{yes|{{{1|}}}}}}
}}<noinclude>
{{Documentation}}
</noinclude>
2a9e67bf7493f3014705d612ba3132ca42647826
Module:Page
828
94
183
182
2024-08-02T10:51:31Z
黑茶
2
导入1个版本
Scribunto
text/plain
local callAssert = require('Module:CallAssert')
local function main(frame, field)
local args, pargs = frame.args, ( frame:getParent() or {} ).args or {}
local makeTitle=args.makeTitle or pargs.makeTitle
local namespace=args.namespace or pargs.namespace or ""
local fragment=args.fragment or pargs.fragment or ""
local interwiki=args.interwiki or pargs.interwiki or ""
local page=args.page or args[1] or pargs.page or pargs[1] or ""
local id= tonumber( args.id or pargs.id )
local pn = {}
local title -- holds the result of the mw.title.xxx call
for i = 1,9 do pn[i] = args['p'..i] or pargs['p'..i] end
if not id and not mw.ustring.match( page, '%S' ) then page = nil end
if id then
title = callAssert(mw.title.new, 'mw.title.new', id)
elseif not page then
title = callAssert(mw.title.getCurrentTitle, 'getCurrentTitle')
elseif makeTitle then
title = callAssert(mw.title.makeTitle, 'makeTitle', namespace, page, fragment, interwiki)
else
title = callAssert(mw.title.new, 'mw.title.new', page, namespace)
end
local result = title[field]
if type(result) == "function" then
result = result(title, unpack(pn))
end
return tostring(result or "")
end
-- handle all errors in main
main = require('Module:Protect')(main)
local p = {}
-- main function does all the work
local meta = {}
function meta.__index(self, key)
return function(frame)
return main(frame, key)
end
end
setmetatable(p, meta)
function p.getContent(frame)
local args, pargs = frame.args, ( frame:getParent() or {} ).args or {}
local fmt = args.as or pargs.as or "pre"
local text = main(frame, "getContent")
fmt = mw.text.split( fmt, ", ?" )
for _, how in ipairs( fmt ) do
if how == "pre" then
text = table.concat{ "<pre>", text, "</pre>" }
elseif how == "expand" then
text = frame:preprocess(text)
elseif how == "nowiki" then
text = mw.text.nowiki(text)
end
end
return text
end
return p
9b70f0ff53b1c20fd8667c9f3d80167653279cc4
Template:Documentation
10
95
185
184
2024-08-02T10:51:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:documentation|main|_content={{ {{#invoke:documentation|contentTitle}}}}}}
cc4eb5999a198597c14b859d18d2aa7b190e3af0
Template:Ombox
10
96
187
186
2024-08-02T10:51:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:Message box|ombox}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
0e54065432d540737b9e56c4e3a8e7f74d4534ea
Module:Documentation
828
97
189
188
2024-08-02T10:51:33Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[那艺娜维基:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[那艺娜维基:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[那艺娜维基:Template documentation|documentation]]
-- is [[那艺娜维基:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[那艺娜维基:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2c374c042ebd8bc4d2d63d207aa078459069c065
Module:Documentation/config
828
98
191
190
2024-08-02T10:51:34Z
黑茶
2
导入1个版本
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[那艺娜维基:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[那艺娜维基:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[那艺娜维基:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
c0991af7f04ef8f2b12d94f64d2e0ea5968d2413
Module:File link
828
99
193
192
2024-08-02T10:51:34Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides a library for formatting file wikilinks.
local yesno = require('Module:Yesno')
local checkType = require('libraryUtil').checkType
local p = {}
function p._main(args)
checkType('_main', 1, args, 'table')
-- This is basically libraryUtil.checkTypeForNamedArg, but we are rolling our
-- own function to get the right error level.
local function checkArg(key, val, level)
if type(val) ~= 'string' then
error(string.format(
"type error in '%s' parameter of '_main' (expected string, got %s)",
key, type(val)
), level)
end
end
local ret = {}
-- Adds a positional parameter to the buffer.
local function addPositional(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#ret + 1] = val
end
-- Adds a named parameter to the buffer. We assume that the parameter name
-- is the same as the argument key.
local function addNamed(key)
local val = args[key]
if not val then
return nil
end
checkArg(key, val, 4)
ret[#ret + 1] = key .. '=' .. val
end
-- Filename
checkArg('file', args.file, 3)
ret[#ret + 1] = 'File:' .. args.file
-- Format
if args.format then
checkArg('format', args.format)
if args.formatfile then
checkArg('formatfile', args.formatfile)
ret[#ret + 1] = args.format .. '=' .. args.formatfile
else
ret[#ret + 1] = args.format
end
end
-- Border
if yesno(args.border) then
ret[#ret + 1] = 'border'
end
addPositional('location')
addPositional('alignment')
addPositional('size')
addNamed('upright')
addNamed('link')
addNamed('alt')
addNamed('page')
addNamed('class')
addNamed('lang')
addNamed('start')
addNamed('end')
addNamed('thumbtime')
addPositional('caption')
return string.format('[[%s]]', table.concat(ret, '|'))
end
function p.main(frame)
local origArgs = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:File link'
})
if not origArgs.file then
error("'file' parameter missing from [[Template:File link]]", 0)
end
-- Copy the arguments that were passed to a new table to avoid looking up
-- every possible parameter in the frame object.
local args = {}
for k, v in pairs(origArgs) do
-- Make _BLANK a special argument to add a blank parameter. For use in
-- conditional templates etc. it is useful for blank arguments to be
-- ignored, but we still need a way to specify them so that we can do
-- things like [[File:Example.png|link=]].
if v == '_BLANK' then
v = ''
end
args[k] = v
end
return p._main(args)
end
return p
66925f088d11530f2482f04181a3baaaa0ad3d0c
Template:T1
10
100
195
194
2024-08-02T10:51:35Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Tl]] {{错字重定向}}
be295331905847cbb58c82c268a1165f8cd1dad5
Template:Documentation subpage
10
101
197
196
2024-08-02T10:51:35Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[那艺娜维基:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
a29fcace7b5ee767264d3f8874aa71d0eb6ec03d
Template:Sandbox other
10
102
199
198
2024-08-02T10:51:36Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{#ifeq:{{SUBPAGENAME}}|sandbox|1}}{{#invoke:String|match|{{PAGENAME}}|/sandbox/styles.css$|plain=false|nomatch=}}|{{{1|}}}|{{{2|}}}}}<!--
--><noinclude>{{documentation}}</noinclude>
3462b190d62e7d7ed1a408cd5607c5c124a1ce15
Module:About
828
103
201
200
2024-08-02T10:51:37Z
黑茶
2
导入1个版本
Scribunto
text/plain
local mArguments --initialize lazily
local ifmobile = require('Module:If mobile')
local mHatnote = require('Module:Hatnote')
local mHatList = require('Module:Hatnote list')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}
function p.about (frame)
-- A passthrough that gets args from the frame and all
mArguments = require('Module:Arguments')
args = mArguments.getArgs(frame)
return p._about(args)
end
function p._about (args, options)
-- Produces "about" hatnote.
-- Type checks and defaults
checkType('_about', 1, args, 'table', true)
args = args or {}
checkType('_about', 2, options, 'table', true)
options = options or {}
local defaultOptions = {
aboutForm = '此%s介紹的是%s。',
PageType = require('Module:Pagetype').main(),
namespace = mw.title.getCurrentTitle().namespace,
otherText = nil, --included for complete list
sectionString = '章节'
}
for k, v in pairs(defaultOptions) do
if options[k] == nil then options[k] = v end
end
-- Set initial "about" string
local pageType = (args.section and options.sectionString) or options.PageType
local about = ''
if args[1] then
about = string.format(options.aboutForm, pageType, args[1])
end
--Allow passing through certain options
local fsOptions = {
otherText = options.otherText,
extratext = args.text
}
local hnOptions = {
selfref = args.selfref
}
-- Set for-see list
local forSee = mHatList._forSee(args, 2, fsOptions)
local image = '[[File:Disambig_gray.svg|25px|link=那艺娜维基:消歧义|alt=]]'
local mobview = ifmobile._main({nil, ' '})
-- Concatenate and return
return mHatnote._hatnote(image .. mobview .. about .. forSee, hnOptions)
end
return p
a1e813f1f5c49f3f63e65f0d5a8e6c47473f738e
Template:Lua
10
104
203
202
2024-08-02T10:51:37Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Uses Lua]]
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
{{模板捷徑重定向}}
}}
c08eca5e48152ab4733cd1afe7dc46252e4402e3
Template:Uses Lua
10
105
205
204
2024-08-02T10:51:37Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#iferror:{{#invoke:Lua banner|main}}|{{#invoke:Lua banner|main2}}}}</includeonly><noinclude>
{{ {{FULLPAGENAME}} |Module:Lua banner}}
{{模板文件}}
</noinclude>
ec2cfd9808cb58e75e6f7687c9b85dd98ee2db4e
Template:TemplateDataHeader
10
106
207
206
2024-08-02T10:51:38Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:TemplateData header]]
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
}}
137e325b30019855f5d44e9ad939deb1de931e33
Template:TemplateData header
10
107
209
208
2024-08-02T10:51:38Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="templatedata-header">{{#if:{{{noheader|}}}| |以下是该模板的{{#if:{{{nolink|}}}|-{zh-cn:模板数据;zh-tw:模板資料}-|[[那艺娜维基:模板数据|-{zh-cn:模板数据;zh-tw:模板資料}-]]}},适用于[[那艺娜维基:可视化编辑器|-{zh-cn:可视化编辑器;zh-tw:視覺化編輯器;}-]]等工具。}}
'''{{{1|{{BASEPAGENAME}}}}}-{zh-cn:模板数据;zh-tw:模板資料}-'''
</div><includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:模板数据文档]]
}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
d02fc282d251516ba7c50d0ba1fbca94c816036d
Module:Lua banner
828
108
211
210
2024-08-02T10:51:39Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[那艺娜维基:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
dc0cc1f5c839b737e09cd1889b2121194b550c65
Module:Protection banner
828
109
213
212
2024-08-02T10:51:39Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{pp-meta}} and its daughter templates such as
-- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.
-- Initialise necessary modules.
require('Module:No globals')
local makeFileLink = require('Module:File link')._main
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main
local yesno = require('Module:Yesno')
-- Lazily initialise modules and objects we don't always need.
local getArgs, makeMessageBox, lang
-- Set constants.
local CONFIG_MODULE = 'Module:Protection banner/config'
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function makeCategoryLink(cat, sort)
if cat then
return string.format(
'[[%s:%s|%s]]',
mw.site.namespaces[14].name,
cat,
sort
)
end
end
-- Validation function for the expiry and the protection date
local function validateDate(dateString, dateType)
if not lang then
lang = mw.language.getContentLanguage()
end
local success, result = pcall(lang.formatDate, lang, 'U', dateString)
if success then
result = tonumber(result)
if result then
return result
end
end
error(string.format(
'%s「%s」並非有效的格式!',
dateType,
tostring(dateString)
), 4)
end
local function makeFullUrl(page, query, display)
return require('Module:Fullurl')._fullurl2(page, query, display)
end
-- Given a directed graph formatted as node -> table of direct successors,
-- get a table of all nodes reachable from a given node (though always
-- including the given node).
local function getReachableNodes(graph, start)
local toWalk, retval = {[start] = true}, {}
while true do
-- Can't use pairs() since we're adding and removing things as we're iterating
local k = next(toWalk) -- This always gets the "first" key
if k == nil then
return retval
end
toWalk[k] = nil
retval[k] = true
for _,v in ipairs(graph[k]) do
if not retval[v] then
toWalk[v] = true
end
end
end
end
--------------------------------------------------------------------------------
-- Protection class
--------------------------------------------------------------------------------
local Protection = {}
Protection.__index = Protection
Protection.supportedActions = {
edit = true,
move = true,
autoreview = true,
upload = true
}
Protection.bannerConfigFields = {
'text',
'explanation',
'tooltip',
'alt',
'link',
'image'
}
function Protection.new(args, cfg, title)
local obj = {}
obj._cfg = cfg
obj.title = title or mw.title.getCurrentTitle()
-- Set action
if not args.action then
obj.action = 'edit'
elseif Protection.supportedActions[args.action] then
obj.action = args.action
else
error(string.format(
'未知動作「%s」',
tostring(args.action)
), 3)
end
-- Set level
obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)
if not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then
-- Users need to be autoconfirmed to move pages anyway, so treat
-- semi-move-protected pages as unprotected.
obj.level = '*'
end
-- Set expiry
local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title)
if effectiveExpiry == 'infinity' then
obj.expiry = 'indef'
elseif effectiveExpiry ~= 'unknown' then
obj.expiry = validateDate(effectiveExpiry, '截止時間')
end
-- Set reason
if args[1] then
obj.reason = mw.ustring.lower(args[1])
if obj.reason:find('|') then
error('理由中不得存在「|」!', 3)
end
end
-- Set protection date
if args.date then
obj.protectionDate = validateDate(args.date, '保護日期')
end
-- Set banner config
do
obj.bannerConfig = {}
local configTables = {}
if cfg.banners[obj.action] then
configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason]
end
if cfg.defaultBanners[obj.action] then
configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level]
configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default
end
configTables[#configTables + 1] = cfg.masterBanner
for i, field in ipairs(Protection.bannerConfigFields) do
for j, t in ipairs(configTables) do
if t[field] then
obj.bannerConfig[field] = t[field]
break
end
end
end
end
return setmetatable(obj, Protection)
end
function Protection:isProtected()
return self.level ~= '*'
end
function Protection:isTemporary()
return type(self.expiry) == 'number'
end
function Protection:makeProtectionCategory()
local cfg = self._cfg
local title = self.title
-- Exit if the page is not protected.
if not self:isProtected() then
return ''
end
-- Get the expiry key fragment.
local expiryFragment
if self.expiry == 'indef' then
expiryFragment = self.expiry
elseif type(self.expiry) == 'number' then
expiryFragment = 'temp'
end
-- Get the namespace key fragment.
local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]
if not namespaceFragment and title.namespace % 2 == 1 then
namespaceFragment = 'talk'
end
-- Define the order that key fragments are tested in. This is done with an
-- array of tables containing the value to be tested, along with its
-- position in the cfg.protectionCategories table.
local order = {
{val = expiryFragment, keypos = 1},
{val = namespaceFragment, keypos = 2},
{val = self.reason, keypos = 3},
{val = self.level, keypos = 4},
{val = self.action, keypos = 5}
}
--[[
-- The old protection templates used an ad-hoc protection category system,
-- with some templates prioritising namespaces in their categories, and
-- others prioritising the protection reason. To emulate this in this module
-- we use the config table cfg.reasonsWithNamespacePriority to set the
-- reasons for which namespaces have priority over protection reason.
-- If we are dealing with one of those reasons, move the namespace table to
-- the end of the order table, i.e. give it highest priority. If not, the
-- reason should have highest priority, so move that to the end of the table
-- instead.
--]]
table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3))
--[[
-- Define the attempt order. Inactive subtables (subtables with nil "value"
-- fields) are moved to the end, where they will later be given the key
-- "all". This is to cut down on the number of table lookups in
-- cfg.protectionCategories, which grows exponentially with the number of
-- non-nil keys. We keep track of the number of active subtables with the
-- noActive parameter.
--]]
local noActive, attemptOrder
do
local active, inactive = {}, {}
for i, t in ipairs(order) do
if t.val then
active[#active + 1] = t
else
inactive[#inactive + 1] = t
end
end
noActive = #active
attemptOrder = active
for i, t in ipairs(inactive) do
attemptOrder[#attemptOrder + 1] = t
end
end
--[[
-- Check increasingly generic key combinations until we find a match. If a
-- specific category exists for the combination of key fragments we are
-- given, that match will be found first. If not, we keep trying different
-- key fragment combinations until we match using the key
-- "all-all-all-all-all".
--
-- To generate the keys, we index the key subtables using a binary matrix
-- with indexes i and j. j is only calculated up to the number of active
-- subtables. For example, if there were three active subtables, the matrix
-- would look like this, with 0 corresponding to the key fragment "all", and
-- 1 corresponding to other key fragments.
--
-- j 1 2 3
-- i
-- 1 1 1 1
-- 2 0 1 1
-- 3 1 0 1
-- 4 0 0 1
-- 5 1 1 0
-- 6 0 1 0
-- 7 1 0 0
-- 8 0 0 0
--
-- Values of j higher than the number of active subtables are set
-- to the string "all".
--
-- A key for cfg.protectionCategories is constructed for each value of i.
-- The position of the value in the key is determined by the keypos field in
-- each subtable.
--]]
local cats = cfg.protectionCategories
for i = 1, 2^noActive do
local key = {}
for j, t in ipairs(attemptOrder) do
if j > noActive then
key[t.keypos] = 'all'
else
local quotient = i / 2 ^ (j - 1)
quotient = math.ceil(quotient)
if quotient % 2 == 1 then
key[t.keypos] = t.val
else
key[t.keypos] = 'all'
end
end
end
key = table.concat(key, '|')
local attempt = cats[key]
if attempt then
return makeCategoryLink(attempt, title.text)
end
end
return ''
end
function Protection:isIncorrect()
local expiry = self.expiry
return not self:isProtected()
or type(expiry) == 'number' and expiry < os.time()
end
function Protection:isTemplateProtectedNonTemplate()
local action, namespace = self.action, self.title.namespace
return self.level == 'templateeditor'
and (
(action ~= 'edit' and action ~= 'move')
or (namespace ~= 10 and namespace ~= 828)
)
end
function Protection:makeCategoryLinks()
local msg = self._cfg.msg
local ret = { self:makeProtectionCategory() }
if self:isIncorrect() then
ret[#ret + 1] = makeCategoryLink(
msg['tracking-category-incorrect'],
self.title.text
)
end
if self:isTemplateProtectedNonTemplate() then
ret[#ret + 1] = makeCategoryLink(
msg['tracking-category-template'],
self.title.text
)
end
return table.concat(ret)
end
--------------------------------------------------------------------------------
-- Blurb class
--------------------------------------------------------------------------------
local Blurb = {}
Blurb.__index = Blurb
Blurb.bannerTextFields = {
text = true,
explanation = true,
tooltip = true,
alt = true,
link = true
}
function Blurb.new(protectionObj, args, cfg)
return setmetatable({
_cfg = cfg,
_protectionObj = protectionObj,
_args = args
}, Blurb)
end
-- Private methods --
function Blurb:_formatDate(num)
-- Formats a Unix timestamp into dd Month, YYYY format.
lang = lang or mw.language.getContentLanguage()
local success, date = pcall(
lang.formatDate,
lang,
self._cfg.msg['expiry-date-format'] or 'j F Y',
'@' .. tostring(num)
)
if success then
return date
end
end
function Blurb:_getExpandedMessage(msgKey)
return self:_substituteParameters(self._cfg.msg[msgKey])
end
function Blurb:_substituteParameters(msg)
if not self._params then
local parameterFuncs = {}
parameterFuncs.CURRENTVERSION = self._makeCurrentVersionParameter
parameterFuncs.EDITREQUEST = self._makeEditRequestParameter
parameterFuncs.EXPIRY = self._makeExpiryParameter
parameterFuncs.EXPLANATIONBLURB = self._makeExplanationBlurbParameter
parameterFuncs.IMAGELINK = self._makeImageLinkParameter
parameterFuncs.INTROBLURB = self._makeIntroBlurbParameter
parameterFuncs.INTROFRAGMENT = self._makeIntroFragmentParameter
parameterFuncs.PAGETYPE = self._makePagetypeParameter
parameterFuncs.PROTECTIONBLURB = self._makeProtectionBlurbParameter
parameterFuncs.PROTECTIONDATE = self._makeProtectionDateParameter
parameterFuncs.PROTECTIONLEVEL = self._makeProtectionLevelParameter
parameterFuncs.PROTECTIONLOG = self._makeProtectionLogParameter
parameterFuncs.TALKPAGE = self._makeTalkPageParameter
parameterFuncs.TOOLTIPBLURB = self._makeTooltipBlurbParameter
parameterFuncs.TOOLTIPFRAGMENT = self._makeTooltipFragmentParameter
parameterFuncs.VANDAL = self._makeVandalTemplateParameter
self._params = setmetatable({}, {
__index = function (t, k)
local param
if parameterFuncs[k] then
param = parameterFuncs[k](self)
end
param = param or ''
t[k] = param
return param
end
})
end
msg = msg:gsub('${(%u+)}', self._params)
return msg
end
function Blurb:_makeCurrentVersionParameter()
-- A link to the page history or the move log, depending on the kind of
-- protection.
local pagename = self._protectionObj.title.prefixedText
if self._protectionObj.action == 'move' then
-- We need the move log link.
return makeFullUrl(
'Special:Log',
{type = 'move', page = pagename},
self:_getExpandedMessage('current-version-move-display')
)
else
-- We need the history link.
return makeFullUrl(
pagename,
{action = 'history'},
self:_getExpandedMessage('current-version-edit-display')
)
end
end
function Blurb:_makeEditRequestParameter()
local mEditRequest = require('Module:Submit an edit request')
local action = self._protectionObj.action
local level = self._protectionObj.level
-- Get the edit request type.
local requestType
if action == 'edit' then
if level == 'autoconfirmed' then
requestType = 'semi'
elseif level == 'extendedconfirmed' then
requestType = 'extended'
elseif level == 'templateeditor' then
requestType = 'template'
end
end
requestType = requestType or 'full'
-- Get the display value.
local display = self:_getExpandedMessage('edit-request-display')
return mEditRequest._link{type = requestType, display = display}
end
function Blurb:_makeExpiryParameter()
local expiry = self._protectionObj.expiry
if type(expiry) == 'number' then
return self:_formatDate(expiry)
else
return expiry
end
end
function Blurb:_makeExplanationBlurbParameter()
-- Cover special cases first.
if self._protectionObj.title.namespace == 8 then
-- MediaWiki namespace
return self:_getExpandedMessage('explanation-blurb-nounprotect')
end
-- Get explanation blurb table keys
local action = self._protectionObj.action
local level = self._protectionObj.level
local talkKey = self._protectionObj.title.isTalkPage and 'talk' or 'subject'
-- Find the message in the explanation blurb table and substitute any
-- parameters.
local explanations = self._cfg.explanationBlurbs
local msg
if explanations[action][level] and explanations[action][level][talkKey] then
msg = explanations[action][level][talkKey]
elseif explanations[action][level] and explanations[action][level].default then
msg = explanations[action][level].default
elseif explanations[action].default and explanations[action].default[talkKey] then
msg = explanations[action].default[talkKey]
elseif explanations[action].default and explanations[action].default.default then
msg = explanations[action].default.default
else
istalk = talkKey == 'talk' and true or false
error(string.format(
'找不到 action=%s protectionlevel=%s istalkpage=%s 時的解釋說明',
action,
level,
istalk
), 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeImageLinkParameter()
local imageLinks = self._cfg.imageLinks
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if imageLinks[action][level] then
msg = imageLinks[action][level]
elseif imageLinks[action].default then
msg = imageLinks[action].default
else
msg = imageLinks.edit.default
end
return self:_substituteParameters(msg)
end
function Blurb:_makeIntroBlurbParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('intro-blurb-expiry')
else
return self:_getExpandedMessage('intro-blurb-noexpiry')
end
end
function Blurb:_makeIntroFragmentParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('intro-fragment-expiry')
else
return self:_getExpandedMessage('intro-fragment-noexpiry')
end
end
function Blurb:_makePagetypeParameter()
local pagetypes = self._cfg.pagetypes
return pagetypes[self._protectionObj.title.namespace]
or pagetypes.default
or error('「pagetypes.default」丟失!', 8)
end
function Blurb:_makeProtectionBlurbParameter()
local protectionBlurbs = self._cfg.protectionBlurbs
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if protectionBlurbs[action][level] then
msg = protectionBlurbs[action][level]
elseif protectionBlurbs[action].default then
msg = protectionBlurbs[action].default
elseif protectionBlurbs.edit.default then
msg = protectionBlurbs.edit.default
else
error('沒有為「protectionBlurbs.edit.default」定義保護說明!', 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeProtectionDateParameter()
local protectionDate = self._protectionObj.protectionDate
if type(protectionDate) == 'number' then
return self:_formatDate(protectionDate)
else
return protectionDate
end
end
function Blurb:_makeProtectionLevelParameter()
local protectionLevels = self._cfg.protectionLevels
local action = self._protectionObj.action
local level = self._protectionObj.level
local msg
if protectionLevels[action][level] then
msg = protectionLevels[action][level]
elseif protectionLevels[action].default then
msg = protectionLevels[action].default
elseif protectionLevels.edit.default then
msg = protectionLevels.edit.default
else
error('沒有為「protectionLevels.edit.default」定義保護級別!', 8)
end
return self:_substituteParameters(msg)
end
function Blurb:_makeProtectionLogParameter()
local pagename = self._protectionObj.title.prefixedText
if self._protectionObj.action == 'autoreview' then
-- We need the pending changes log.
return makeFullUrl(
'Special:Log',
{type = 'stable', page = pagename},
self:_getExpandedMessage('pc-log-display')
)
else
-- We need the protection log.
return makeFullUrl(
'Special:Log',
{type = 'protect', page = pagename},
self:_getExpandedMessage('protection-log-display')
)
end
end
function Blurb:_makeTalkPageParameter()
return string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[self._protectionObj.title.namespace].talk.name,
self._protectionObj.title.text,
self._args.section or 'top',
self:_getExpandedMessage('talk-page-link-display')
)
end
function Blurb:_makeTooltipBlurbParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('tooltip-blurb-expiry')
else
return self:_getExpandedMessage('tooltip-blurb-noexpiry')
end
end
function Blurb:_makeTooltipFragmentParameter()
if self._protectionObj:isTemporary() then
return self:_getExpandedMessage('tooltip-fragment-expiry')
else
return self:_getExpandedMessage('tooltip-fragment-noexpiry')
end
end
function Blurb:_makeVandalTemplateParameter()
return require('Module:Vandal-m')._main{
self._args.user or self._protectionObj.title.baseText
}
end
-- Public methods --
function Blurb:makeBannerText(key)
-- Validate input.
if not key or not Blurb.bannerTextFields[key] then
error(string.format(
'「%s」不是有效的橫幅配置金鑰。',
tostring(key)
), 2)
end
-- Generate the text.
local msg = self._protectionObj.bannerConfig[key]
if type(msg) == 'string' then
return self:_substituteParameters(msg)
elseif type(msg) == 'function' then
msg = msg(self._protectionObj, self._args)
if type(msg) ~= 'string' then
error(string.format(
'解析橫幅配置時生成錯誤「%s」',
tostring(key),
type(msg)
), 4)
end
return self:_substituteParameters(msg)
end
end
--------------------------------------------------------------------------------
-- BannerTemplate class
--------------------------------------------------------------------------------
local BannerTemplate = {}
BannerTemplate.__index = BannerTemplate
function BannerTemplate.new(protectionObj, cfg)
local obj = {}
obj._cfg = cfg
-- Set the image filename.
local imageFilename = protectionObj.bannerConfig.image
if imageFilename then
obj._imageFilename = imageFilename
else
-- If an image filename isn't specified explicitly in the banner config,
-- generate it from the protection status and the namespace.
local action = protectionObj.action
local level = protectionObj.level
local namespace = protectionObj.title.namespace
local reason = protectionObj.reason
-- Deal with special cases first.
if (
namespace == 10
or namespace == 828
or reason and obj._cfg.indefImageReasons[reason]
)
and action == 'edit'
and level == 'sysop'
and not protectionObj:isTemporary()
then
-- Fully protected modules and templates get the special red "indef"
-- padlock.
obj._imageFilename = obj._cfg.msg['image-filename-indef']
else
-- Deal with regular protection types.
local images = obj._cfg.images
if images[action] then
if images[action][level] then
obj._imageFilename = images[action][level]
elseif images[action].default then
obj._imageFilename = images[action].default
end
end
end
end
return setmetatable(obj, BannerTemplate)
end
function BannerTemplate:renderImage()
local filename = self._imageFilename
or self._cfg.msg['image-filename-default']
or 'Transparent.gif'
return makeFileLink{
file = filename,
size = (self.imageWidth or 20) .. 'px',
alt = self._imageAlt,
link = self._imageLink,
caption = self.imageCaption
}
end
--------------------------------------------------------------------------------
-- Banner class
--------------------------------------------------------------------------------
local Banner = setmetatable({}, BannerTemplate)
Banner.__index = Banner
function Banner.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj.imageWidth = 40
obj.imageCaption = blurbObj:makeBannerText('alt') -- Large banners use the alt text for the tooltip.
obj._reasonText = blurbObj:makeBannerText('text')
obj._explanationText = blurbObj:makeBannerText('explanation')
obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing.
return setmetatable(obj, Banner)
end
function Banner:__tostring()
-- Renders the banner.
makeMessageBox = makeMessageBox or require('Module:Message box').main
local reasonText = self._reasonText or error('沒有理由!', 2)
local explanationText = self._explanationText
local mbargs = {
page = self._page,
type = 'protection',
image = self:renderImage(),
text = string.format(
"'''%s'''%s",
reasonText,
explanationText and '<br />' .. explanationText or ''
)
}
return makeMessageBox('mbox', mbargs)
end
--------------------------------------------------------------------------------
-- Padlock class
--------------------------------------------------------------------------------
local Padlock = setmetatable({}, BannerTemplate)
Padlock.__index = Padlock
function Padlock.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj.imageWidth = 20
obj.imageCaption = blurbObj:makeBannerText('tooltip')
obj._imageAlt = blurbObj:makeBannerText('alt')
obj._imageLink = blurbObj:makeBannerText('link')
obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action]
or cfg.padlockIndicatorNames.default
or 'pp-default'
return setmetatable(obj, Padlock)
end
function Padlock:__tostring()
local frame = mw.getCurrentFrame()
-- The nowiki tag helps prevent whitespace at the top of articles.
return frame:extensionTag{name = 'nowiki'} .. frame:extensionTag{
name = 'indicator',
args = {name = self._indicatorName},
content = self:renderImage()
}
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
-- This is used for testing purposes.
return {
Protection = Protection,
Blurb = Blurb,
BannerTemplate = BannerTemplate,
Banner = Banner,
Padlock = Padlock,
}
end
function p._main(args, cfg, title)
args = args or {}
cfg = cfg or require(CONFIG_MODULE)
local protectionObj = Protection.new(args, cfg, title)
local ret = {}
-- If a page's edit protection is equally or more restrictive than its
-- protection from some other action, then don't bother displaying anything
-- for the other action (except categories).
if protectionObj.action == 'edit' or
args.demolevel or
not getReachableNodes(
cfg.hierarchy,
protectionObj.level
)[effectiveProtectionLevel('edit', protectionObj.title)]
then
-- Initialise the blurb object
local blurbObj = Blurb.new(protectionObj, args, cfg)
-- Render the banner
if protectionObj:isProtected() then
ret[#ret + 1] = tostring(
(yesno(args.small) and Padlock or Banner)
.new(protectionObj, blurbObj, cfg)
)
end
end
-- Render the categories
if yesno(args.category) ~= false then
ret[#ret + 1] = protectionObj:makeCategoryLinks()
end
return table.concat(ret)
end
function p.main(frame, cfg)
cfg = cfg or require(CONFIG_MODULE)
-- Find default args, if any.
local parent = frame.getParent and frame:getParent()
local defaultArgs = parent and cfg.wrappers[parent:getTitle():gsub('/sandbox$', '')]
-- Find user args, and use the parent frame if we are being called from a
-- wrapper template.
getArgs = getArgs or require('Module:Arguments').getArgs
local userArgs = getArgs(frame, {
parentOnly = defaultArgs,
frameOnly = not defaultArgs
})
-- Build the args table. User-specified args overwrite default args.
local args = {}
for k, v in pairs(defaultArgs or {}) do
args[k] = v
end
for k, v in pairs(userArgs) do
args[k] = v
end
return p._main(args, cfg)
end
return p
0c5173a5a01ad7424318edf28b14b67825cc186a
Module:Effective protection expiry
828
110
215
214
2024-08-02T10:51:40Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
-- Returns the expiry of a restriction of an action on a given title, or unknown if it cannot be known.
-- If no title is specified, the title of the page being displayed is used.
function p._main(action, pagename)
local title
if type(pagename) == 'table' and pagename.prefixedText then
title = pagename
elseif pagename then
title = mw.title.new(pagename)
else
title = mw.title.getCurrentTitle()
end
pagename = title.prefixedText
if action == 'autoreview' then
local stabilitySettings = mw.ext.FlaggedRevs.getStabilitySettings(title)
return stabilitySettings and stabilitySettings.expiry or 'unknown'
elseif action ~= 'edit' and action ~= 'move' and action ~= 'create' and action ~= 'upload' then
error( 'First parameter must be one of edit, move, create, upload, autoreview', 2 )
end
local rawExpiry = mw.getCurrentFrame():callParserFunction('PROTECTIONEXPIRY', action, pagename)
if rawExpiry == 'infinity' then
return 'infinity'
elseif rawExpiry == '' then
return 'unknown'
else
local year, month, day, hour, minute, second = rawExpiry:match(
'^(%d%d%d%d)(%d%d)(%d%d)(%d%d)(%d%d)(%d%d)$'
)
if year then
return string.format(
'%s-%s-%sT%s:%s:%s',
year, month, day, hour, minute, second
)
else
error('internal error in Module:Effective protection expiry; malformed expiry timestamp')
end
end
end
setmetatable(p, { __index = function(t, k)
return function(frame)
return t._main(k, frame.args[1])
end
end })
return p
9a8c58dc2667232ed08a9b206a5d89ca8150312b
Module:Protection banner/config
828
111
217
216
2024-08-02T10:51:41Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[那艺娜维基:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[那艺娜维基:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[那艺娜维基:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[那艺娜维基:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[那艺娜维基:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[那艺娜维基:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[那艺娜维基:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[那艺娜维基:封禁方针|封禁]]或被'
.. '[[那艺娜维基:編輯禁制方針|編輯禁制]]用户的[[那艺娜维基:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[那艺娜维基:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[那艺娜维基:高風險模板|高風險模板]],'
.. '已被永久[[那艺娜维基:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]或'
.. '[[那艺娜维基:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏|破坏]]而被保护的页面',
text = '由于[[那艺娜维基:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[那艺娜维基:用户权限'
.. '级别#新用户|新用户]]或[[那艺娜维基:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[那艺娜维基:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[那艺娜维基:用户权限级别#新用户|新用户]] or'
.. ' [[那艺娜维基:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[那艺娜维基:Reviewing|reviewers]] or'
.. ' [[那艺娜维基:管理员|管理员]] are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[那艺娜维基:共识'
.. '|共识]]基础,您可以向'
.. '[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[那艺娜维基:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[那艺娜维基:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[那艺娜维基:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[那艺娜维基:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = '那艺娜维基:保護方針#全保护',
templateeditor = '那艺娜维基:保護方針#模板保护',
extendedconfirmed = '那艺娜维基:保護方針#延伸確認保護',
autoconfirmed = '那艺娜维基:保護方針#半保护'
},
move = {
default = '那艺娜维基:保護方針#移动保护'
},
autoreview = {
autoconfirmed = '那艺娜维基:保護方針#pc1',
reviewer = '那艺娜维基:保護方針#pc2'
},
upload = {
default = '那艺娜维基:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[那艺娜维基:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
7094c99bbb3daa4ca9c6e7979c5de465b77c2398
Module:Protect
828
112
219
218
2024-08-02T10:51:41Z
黑茶
2
导入1个版本
Scribunto
text/plain
local function processResult(options, success, ...)
if not success then
local message = tostring(... or '(no message)')
if options.removeLocation then
message = string.gsub(message, '^Module:[^:]+:%d+: ', '', 1)
end
return string.format(options.errFormat, message)
end
return ...
end
local function protect(func, errFormat, options)
if type(errFormat) == 'table' then
options = options or errFormat
errFormat = nil
end
options = mw.clone(options) or {}
options.errFormat = errFormat or options.errFormat or 'Error: %s'
if not options.raw then
options.errFormat = '<strong class="error">' .. options.errFormat .. '</strong>'
end
options.removeLocation = options.removeLocation == nil or options.removeLocation
return function (...)
return processResult(options, pcall(func, ...))
end
end
return protect
b9ef98da3f3df35e58a7136f9a9c73a12aa8b35d
Template:High-use
10
113
221
220
2024-08-02T10:51:41Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:High-use|main|1={{{1|}}}|2={{{2|}}}|all-pages={{{all-pages|}}}|info={{{info|}}}|demo={{{demo|}}}|form={{{form|}}}|expiry={{{expiry|}}}}}<noinclude>
{{Documentation}}
<!-- Add categories to the /doc subpage; interwiki links go to Wikidata, thank you! -->
</noinclude>
a0b2a1139d339dbb30f81db49ec4775f8d55871f
Module:High-use
828
114
223
222
2024-08-02T10:51:42Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
local _fetch = require('Module:Transclusion_count').fetch
local nspn = mw.getCurrentFrame():preprocess('{{Namespace pagename}}')
local _separated_entries = require('Module:Separated entries').main
function p.num(frame, count)
if count == nil then count = _fetch(frame) end
-- Build output string
local return_value = ""
if count == nil then
if frame.args[1] == "risk" then
return_value = "大量頁面"
else
return_value = "許多頁面"
end
else
-- Use 2 significant figures for smaller numbers and 3 for larger ones
local sigfig = 2
if count >= 100000 then
sigfig = 3
end
-- Prepare to round to appropriate number of sigfigs
local f = math.floor(math.log10(count)) - sigfig + 1
-- Round and insert "approximately" or "+" when appropriate
if (frame.args[2] == "yes") or (mw.ustring.sub(frame.args[1],-1) == "+") then
-- Round down
return_value = string.format("%s+個頁面", mw.getContentLanguage():formatNum(math.floor( (count / 10^(f)) ) * (10^(f))) )
else
-- Round to nearest
return_value = string.format("約%s個頁面", mw.getContentLanguage():formatNum(math.floor( (count / 10^(f)) + 0.5) * (10^(f))) )
end
-- Insert percent of pages
if frame.args["all-pages"] and frame.args["all-pages"] ~= "" then
local percent = math.floor( ( (count/frame:callParserFunction('NUMBEROFPAGES', 'R') ) * 100) + 0.5)
return_value = string.format("%s,佔全部頁面的%s%%", return_value, percent)
end
end
return return_value
end
-- Actions if there is a large (greater than or equal to 100,000) transclusion count
function p.risk(frame)
local return_value = ""
if frame.args[1] == "risk" then
return_value = "risk"
else
local count = _fetch(frame)
if count and count >= 100000 then return_value = "risk" end
end
return return_value
end
function p.text(frame, count)
local bot_text = "\n\n----\n<small>模板引用數量會自動更新。</small>"
if frame.args["nobot"] == "true" then
bot_text = ""
end
if count == nil then count = _fetch(frame) end
local return_value = {}
local title = mw.title.getCurrentTitle()
local isdemo = false
if frame.args["demo"] and frame.args["demo"] ~= "" then
isdemo = true
title = mw.title.new(frame.args["demo"], "Template")
end
if title.subpageText == "doc" or title.subpageText == "sandbox" or title.subpageText == "testcases" then
title = title.basePageTitle
end
local templatecount = string.format("https://templatecount.toolforge.org/index.php?lang=zh&namespace=%s&name=%s", title.namespace,mw.uri.encode(title.text))
local used_on_text = string.format("'''%s被引用於[%s %s]'''",
(isdemo and "[["..title.fullText.."]]") or ("此"..nspn),
templatecount,
p.num(frame, count)
)
local sandbox_text = _separated_entries({
string.format("[[%s/sandbox|'''沙盒''']]", title.fullText),
string.format("[[%s/testcases|'''測試樣例''']]", title.fullText),
(title.namespace == 828 and "" or "[[Special:Mypage/沙盒|'''您的沙盒''']]"),
separator="、",
conjunction="或"
})
local info = ""
if frame.args["info"] and frame.args["info"] ~= "" then
info = "<br />" .. frame.args["info"]
end
sandbox_text = string.format("。%s<br /><small>為了避免造成大規模的影響,所有對此%s的編輯應先於%s上測試。</small>",
info, nspn, sandbox_text
)
local discussion_text = string.format("<br /><small>測試後無誤的版本可以一次性地加入此%s中,但是修改前請務必於", nspn)
if frame.args["2"] and frame.args["2"] ~= "" and frame.args["2"] ~= "yes" then
discussion_text = string.format("%s'''[[%s]]'''", discussion_text, frame.args["2"])
else
discussion_text = string.format("%s[[%s|'''討論頁''']]", discussion_text, title.talkPageTitle.fullText )
end
return table.concat({used_on_text, sandbox_text, discussion_text, "發起討論。</small>", bot_text})
end
function p.main(frame)
local count = _fetch(frame)
local return_value = ""
local image = "[[File:Ambox warning yellow.svg|40px|alt=警告|link=]]"
local type_param = "style"
if (frame.args[1] == "risk" or (count and count >= 100000) ) then
image = "[[File:Ambox warning orange.svg|40px|alt=警告|link=]]"
type_param = "content"
end
if frame.args["form"] == "editnotice" then
return_value = frame:expandTemplate{
title = 'editnotice',
args = {
["image"] = image,
["text"] = p.text(frame, count),
["expiry"] = (frame.args["expiry"] or "")
}
}
else
return_value = frame:expandTemplate{
title = 'ombox',
args = {
["type"] = type_param,
["image"] = image,
["text"] = p.text(frame, count),
["expiry"] = (frame.args["expiry"] or "")
}
}
end
return return_value
end
return p
6384bf0a00fa775731ab7d150a48c3516b9d5ee7
Module:Transclusion count
828
115
225
224
2024-08-02T10:51:43Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[那艺娜维基:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
c08ee42f72543653cc35e9f1ae778d67e049f7b4
Template:Hatnote templates
10
116
227
226
2024-08-02T10:51:43Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Navbox
| name = Hatnote templates
| state = {{{state|<includeonly>autocollapse</includeonly>}}}
| tracking = <includeonly>no</includeonly>
| bodyclass = hlist
| belowclass = hlist
| title = [[那艺娜维基:頂註#頂註模板|頂註模板]]
| above =
* [[那艺娜维基:頂註]]
* [[那艺娜维基:消歧义]]
* [[那艺娜维基:重定向]]
| group1 = 主条目
| list1 =
*{{tl|Main}}
*{{tl|Category main}} (页面分类)
*{{t1|Broader}}
| group2 = 通用
| list2 =
*{{tl|Hatnote}}
*{{tl|Self reference}}([[维基百科:格式手冊/避免自我提及|自我提及]])
| group3 = 其他用法
| list3 =
*{{tl|About}}
*{{tl|Other uses}}
*{{tl|About list}}
| group4 = 关于……
| list4 =
*{{tl|For}}
*{{tl|For2}}(自定义文字)
| group5 = 更多信息
| list5 =
*{{tl|Further}}
*{{tl|Further2}}(自定义文字)
| group6 = 参见
| list6 =
*{{tl|See also}}
*{{tl|Category see also}}
*{{tl|Category see also if exists}}
*{{tl|See Wiktionary}}
| group7 = 地点人物
| list7 =
*{{tl|Other people}}
*{{tl|Other places}}
| group8 = 重定向
| list8 =
*{{tl|Redirect}}
*{{tl|Redirect2}}
*{{tl|Redirect-two}}
*{{tl|Redirect-multi}}
*{{tl|Redirect-synonym}}
*{{tl|Redirect list}}
*{{tl|technical reasons}}
| group9 = 消歧义
| list9 =
*{{tl|Distinguish}}
*{{tl|Distinguish2}}
*{{tl|About-distinguish}}
*{{tl|About-distinguish-text}}(自定义文字)
*{{tl|Redirect-distinguish}}
| group10 = 嵌入
| list10 =
*{{tl|Transcluded section}}
*{{t1|Section transclude}}
| group11 = 个别主题
| list11 =
* {{tl|WikiIPA}}
| group12 = 顶注分类
| list12 =
*[[:Category:頂註模板|頂註模板]]
*[[:Category:頂註模塊|顶注模块]]
*[[:Category:列表顶注模板|列表顶注模板]]
| below =
*[[维基百科:頂註#頂註模板|頂註模板文档]]
*{{Icon|cat}} [[:Category:頂註模板]]
}}<noinclude>{{Documentation}}
</noinclude>
912e3eb834ad857373929ea300df0891e2ce28df
Module:Navbar/styles.css
828
117
229
228
2024-08-02T10:51:43Z
黑茶
2
导入1个版本
sanitized-css
text/css
.navbar {
display: inline;
font-weight: normal;
}
.navbar-collapse {
float: left;
text-align: left;
}
.navbar-boxtext {
word-spacing: 0;
}
.navbar ul {
display: inline-block;
white-space: nowrap;
line-height: inherit;
}
.navbar-brackets::before {
margin-right: -0.125em;
content: '[ ';
}
.navbar-brackets::after {
margin-left: -0.125em;
content: ' ]';
}
.navbar li {
word-spacing: -0.125em;
}
.navbar a > span,
.navbar a > abbr {
text-decoration: inherit;
}
.navbar-mini abbr {
font-variant: small-caps;
border-bottom: none;
text-decoration: none;
cursor: inherit;
}
.navbar-ct-full {
font-size: 114%;
margin: 0 7em;
}
.navbar-ct-mini {
font-size: 114%;
margin: 0 4em;
}
97042550467b3dbf0888cf32106715789682e887
Template:High-risk
10
118
231
230
2024-08-02T10:51:44Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#redirect [[Template:High-use]]
e3ccadb5eecb45781d9058d6bea86c3f38f278d1
Module:Transclusion count/data/A
828
119
233
232
2024-08-02T10:51:45Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
["ACG專題"] = 17000,
["ACG專題/class"] = 22000,
["ACG專題/importance"] = 22000,
["AIGA_arrow"] = 5900,
["ARG"] = 3200,
["AUS"] = 7100,
["AUT"] = 2900,
["Abbr"] = 760000,
["About"] = 16000,
["Add_new_taxon"] = 57000,
["Adjacent_stations"] = 18000,
["Adjacent_stations/styles.css"] = 18000,
["AfdLinkNext"] = 9200,
["Age"] = 118000,
["Age_in_years"] = 2100,
["Age_in_years_and_days"] = 2200,
["Albumcover"] = 7200,
["Align"] = 56000,
["AllMovie_title"] = 5300,
["Ambox"] = 223000,
["Ambox/style.css"] = 224000,
["Amg_movie"] = 3600,
["Anchor"] = 6100,
["Antarctica-geo-stub"] = 5200,
["Archive_box"] = 3000,
["Archives"] = 3500,
["Arrow"] = 5900,
["Article"] = 48000,
["ArticleHistory"] = 5500,
["Article_history"] = 8200,
["Articles_by_Importance"] = 3500,
["Articles_by_Quality"] = 6400,
["Articles_by_Quality/down"] = 6400,
["Articles_by_Quality/total"] = 6400,
["Articles_by_Quality/up"] = 6400,
["As_of"] = 2900,
["Asbox"] = 404000,
["Asteroid-stub"] = 6800,
["Audio"] = 9600,
["Austria-geo-stub"] = 2300,
["Authority_control"] = 233000,
["AutoLink"] = 5100,
["Auto_link"] = 2900,
["Autolink"] = 2200,
["Automatic_Taxobox"] = 6500,
["Automatic_taxobox"] = 33000,
["Module:About"] = 16000,
["Module:Adjacent_stations"] = 41000,
["Module:Adjacent_stations/i18n"] = 41000,
["Module:Adjacent_stations/港鐵"] = 2700,
["Module:Age"] = 123000,
["Module:Anchor"] = 6100,
["Module:Arguments"] = 3990000,
["Module:Article_history"] = 8200,
["Module:Article_history/Category"] = 8200,
["Module:Article_history/config"] = 8200,
["Module:Asbox"] = 404000,
["Module:Asbox_stubtree"] = 2500,
["Module:Authority_control"] = 233000,
["Module:Authority_control/auxiliary"] = 59000,
["Module:Authority_control/config"] = 233000,
["Module:Automated_taxobox"] = 33000,
["Module:Autotaxobox"] = 180000,
}
3a63c5444da3214c092266b9bbf97f9a8424e3cc
Template:About/doc
10
120
235
234
2024-08-02T10:51:47Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Documentation subpage}}
<!-- Categories go where indicated at the bottom of this page, please; interwikis go to Wikidata (see also: [[那艺娜维基:Wikidata]]). -->
{{High-risk|8925}}
{{ombox|type=content|text=本模板应在若干页面的名称彼此非常相似时使用,注意请勿滥用。}}
{{Lua|Module:About}}
{{Tlc|About}} 是维基百科中较常用的[[那艺娜维基:頂註|顶注模板]],应当被放置在条目顶端,引导有需要的读者去阅读其他名称相似的页面,使用范例如下:
*{{Tlx|About|Use1}} → {{About|Use1}}
*{{Tlx|About|Use1|<nowiki/>|Article2}} → {{About|Use1||Article2}}
*{{Tlx|About|Use1|<nowiki/>|Article2|和|Article3}} → {{About|Use1||Article2|和|Article3}}
*{{Tlx|About|Use1|Use2|Article2}} → {{About|Use1|Use2|Article2}}
*{{Tlx|About|Use1|Use2|Article2|和|Article3}} → {{About|Use1|Use2|Article2|和|Article3}}
*{{Tlx|About|Use1|Use2|Article2|其他用法}} → {{About|Use1|Use2|Article2|其他用法}}
本模板亦可放置在章节/小节顶端,此时需加入 <code>section=yes</code> 参数:
*{{Tlx|About|Use1|<nowiki>section=yes</nowiki>}} → {{About|Use1|section=yes}}
*{{Tlx|About|Use1|<nowiki/>|Article2|<nowiki>section=yes</nowiki>}} → {{About|Use1||Article2|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|和|Article3|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|和|Article3|section=yes}}
*{{Tlx|About|Use1|Use2|Article2|其他用法|<nowiki>section=yes</nowiki>}} → {{About|Use1|Use2|Article2|其他用法|section=yes}}
本模板同时支持可选参数 {{para|text}},用於添加自定义文字,请务必在其他题注模板无法满足需要时再使用该参数。
==重定向==
*{{Tl|Otheruses4}}
*{{Tl|关于}}
*{{Tl|關於}}
{{Hatnote templates}}
==模板參數==
{{TemplateDataHeader}}
{| class="wikitable sortable"
!colspan=2| 參數
! 描述
! 類型
! 狀態
|-
! 頁面描述
| <code>1</code>
| What the page this template is placed on is about ("This page is about …")
| 字串
| '''必填'''
|-
! 另一頁描述
| <code>2</code>
| What the first other page is about. If unused or blank, defaults to "For other uses".
| 字串
| 建議
|-
! 另一頁標題
| <code>3</code>
| The title of the first other page. If unused, defaults to "[page title] (disambiguation)".
| 頁面
| 建議
|-
! 另二頁描述
| <code>4</code>
| What the second other page is about.
| 字串
| 選填
|-
! 另二頁標題
| <code>5</code>
| The title of the second other page. If unused or blank and parameter 4 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! 另三頁描述
| <code>6</code>
| What the third other page is about.
| 字串
| 選填
|-
! 另三頁標題
| <code>7</code>
| The title of the third other page. If unused or blank and parameter 6 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! 另四頁描述
| <code>8</code>
| What the fourth other page is about.
| 字串
| 選填
|-
! 另四頁標題
| <code>9</code>
| The title of the fourth other page. If unused or blank and parameter 8 exists, defaults to "[page title] (disambiguation)".
| 頁面
| 選填
|-
! Custom text
| <code>section</code>
| Pass "yes" in this parameter to get wording appropriate for use at the top of a section.
;'''Bold text'''
;<code>yes</code>
| 字串
| 選填
|-
! 自定義文本
| <code>text</code>
| Text to be appended to the end.
| 字串
| 選填
|}
<includeonly>{{Sandbox other||
<!-- Categories go below this line, please; interwikis go to Wikidata, thank you! -->
[[Category:消歧义与重定向模板]]
[[Category:顶注模板]]
}}</includeonly><noinclude>[[en:template:About/doc]]</noinclude>
57b9501b52db8b8be1d4d7483234fc5994d3c528
Module:Navbar/configuration
828
121
237
236
2024-08-02T10:51:47Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
['templatestyles'] = 'Module:Navbar/styles.css',
['hlist_templatestyles'] = 'Hlist/styles.css',
['box_text'] = '本模板:', -- default text box when not plain or mini
['title_namespace'] = 'Template', -- namespace to default to for title
['invalid_title'] = '页面不存在 ',
['classes'] = { -- set a line to nil if you don't want it
['navbar'] = 'navbar',
['plainlinks'] = 'plainlinks', -- plainlinks
['horizontal_list'] = 'hlist', -- horizontal list class
['mini'] = 'navbar-mini', -- class indicating small links in the navbar
['this_box'] = 'navbar-boxtext',
['brackets'] = 'navbar-brackets',
-- 'collapsible' is the key for a class to indicate the navbar is
-- setting up the collapsible element in addition to the normal
-- navbar.
['collapsible'] = 'navbar-collapse',
['collapsible_title_mini'] = 'navbar-ct-mini',
['collapsible_title_full'] = 'navbar-ct-full'
}
}
eb732eb337355f0e1de8c27932d500f70419de87
Module:CallAssert
828
122
239
238
2024-08-02T10:51:47Z
黑茶
2
导入1个版本
Scribunto
text/plain
local function pack(...)
return {...}, select('#', ...)
end
local function mapArray(func, array, count)
local result = {}
for i = 1, count or #array do
result[i] = func(array[i])
end
return result
end
local function quote(value)
if type(value) == 'string' then
return (string.gsub(string.format('%q', value), '\\\n', '\\n')) -- Outer parentheses remove second value returned by gsub
end
local str = tostring(value)
if type(value) == 'table' and str ~= 'table' then
return '{' .. str .. '}'
end
return str
end
local function callAssert(func, funcName, ...)
local result, resultCount = pack(func(...))
if not result[1] then
local args, argsCount = pack(...)
args = mapArray(quote, args, argsCount)
local message = mw.ustring.format(
'%s(%s) failed',
funcName,
table.concat(args, ', ')
)
error(message, 2)
end
return unpack(result, 1, resultCount)
end
return callAssert
1f6b71105b007b84f1593a11438484f1ad94f68a
Template:Infobox
10
123
241
240
2024-08-02T10:54:43Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<templatestyles src="Module:Infobox/styles.css" />{{#invoke:Infobox|infobox}}<includeonly>{{template other|{{#ifeq:{{PAGENAME}}|Infobox||{{#ifeq:{{str left|{{SUBPAGENAME}}|7}}|Infobox|[[Category:信息框模板|{{remove first word|{{SUBPAGENAME}}}}]]}}|{{#ifeq:{{PAGENAME}}|信息框||{{#ifeq:{{str rightc|{{SUBPAGENAME}}|3}}|信息框|[[Category:信息框模板|{{str crop|{{SUBPAGENAME}}|3}}]]}}|{{#ifeq:{{PAGENAME}}|資訊框||{{#ifeq:{{str rightc|{{SUBPAGENAME}}|3}}|資訊框|[[Category:信息框模板|{{str crop|{{SUBPAGENAME}}|3}}]]}}}}}}}}|}}</includeonly><noinclude>
{{documentation}}
</noinclude>
6f61b0d555bf7e18b6add1c1aae42bae24a5b237
Module:Category handler/blacklist
828
67
243
129
2024-08-02T10:54:47Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^那艺娜维基:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^那艺娜维基:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
939eea9afe7dd0de8be68d71a9cbccfca2c3d6ee
Template:NoteTA
10
124
245
244
2024-08-02T10:54:48Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:NoteTA|main}}<noinclude>
{{模板文档}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
866263768f3a626ea5c1d5bebbbb17c9ce57983c
Template:Nowrap
10
125
247
246
2024-08-02T10:54:48Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><span class="nowrap">{{{1}}}</span></includeonly><noinclude>{{Documentation}}</noinclude>
6d6bcfa036745c59ef032b1eeed975bfb4a3d395
Module:NoteTA
828
126
249
248
2024-08-02T10:54:49Z
黑茶
2
导入1个版本
Scribunto
text/plain
local z = {}
local WikitextLC = require( 'Module:WikitextLC' )
function Tcode( args )
if args.T == nil or args.T == '' then
return ''
end
local div = mw.html.create( 'div' )
:attr( 'class', 'noteTA-title' )
:attr( 'data-noteta-code', args.T )
:wikitext( WikitextLC.title( args.T ) )
if args.dt ~= nil and args.dt ~= '' then
div:attr( 'data-noteta-desc', args.dt )
end
return tostring( div )
end
function group( name, frame )
if name == nil or name == '' then
return ''
end
local moduleTitle = mw.title.makeTitle( 'Module', 'CGroup/' .. name )
if moduleTitle and moduleTitle.exists then
local data = mw.loadData( 'Module:CGroup/' .. name )
local pieces = {}
if data.content then
for i, v in ipairs( data.content ) do
if v.type == 'item' and v.rule then
table.insert( pieces, '-{H|' .. v.rule .. '}-' )
end
end
return tostring( mw.html.create( 'div' )
:attr( 'data-noteta-group-source', 'module' )
:attr( 'data-noteta-group', data.name or name )
:wikitext( table.concat( pieces ) ) )
end
end
local templateTitle = mw.title.makeTitle( 'Template', 'CGroup/' .. name )
if templateTitle and templateTitle.exists then
return frame:expandTemplate{ title = templateTitle }
end
return tostring( mw.html.create( 'div' )
-- :attr( 'id', 'noteTA-group-' .. mw.uri.anchorEncode( name ) )
:attr( 'data-noteta-group-source', 'none' )
:attr( 'data-noteta-group', name ) )
end
function Gcode( args, frame )
local code = {}
for i = 1, 30 do
table.insert( code, group( args['G' .. i], frame ) )
end
code = table.concat( code )
if code ~= '' then
code = tostring( mw.html.create( 'div' )
:attr( 'class', 'noteTA-group' )
:wikitext( code ) )
if args.G31 ~= nil then
code = code .. '[[Category:NoteTA模板参数使用数量超过限制的页面|G]]'
end
end
return code
end
function local_( i, code, desc )
if code == nil or code == '' then
return ''
end
local div = mw.html.create( 'div' )
-- :attr( 'id', 'noteTA-local-' .. i )
:attr( 'data-noteta-code', code )
:wikitext( WikitextLC.hidden( code ) )
if desc ~= nil and desc ~= '' then
div:attr( 'data-noteta-desc', desc )
end
return tostring( div )
end
function Lcode( args )
local code = {}
for i = 1, 30 do
table.insert( code, local_( i, args[i], args['d' .. i] ) )
end
code = table.concat( code )
if code ~= '' then
code = tostring( mw.html.create( 'div' )
:attr( 'class', 'noteTA-local' )
:wikitext( code ) )
if args[31] ~= nil then
code = code .. '[[Category:NoteTA模板参数使用数量超过限制的页面|L]]'
end
end
return code
end
function z.main( frame )
local args
if frame == mw.getCurrentFrame() then
-- Being called from {{noteTA}}
args = frame:getParent().args
else
-- Being called from another module
args = frame
frame = mw.getCurrentFrame()
end
local Tc = Tcode( args )
local Gc = Gcode( args, frame )
local Lc = Lcode( args )
local code = Tc .. Gc .. Lc
if code ~= '' then
local hash = require( 'Module:Crc32lua' ).crc32( mw.dumpObject( args ) )
code = frame:extensionTag{
name = 'indicator',
content = '[[File:Zh conversion icon m.svg|35px|本页使用了标题或全文手工转换|link=|class=skin-invert]]',
args = { name = string.format( 'noteTA-%x', hash ) },
} .. tostring( mw.html.create( 'div' )
:attr( 'id', string.format( 'noteTA-%x', hash ) )
:attr( 'class', 'noteTA' )
:wikitext( code ) )
if mw.title.getCurrentTitle():inNamespace( 'Template' ) then
code = code .. '[[Category:放置于模板的noteTA]]'
end
end
return code
end
return z
ea994d54783b2d06cd967aa31f96f99dbef2b6b7
Module:WikitextLC
828
127
251
250
2024-08-02T10:54:49Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
--- Construct an inline conversion from a table input.
-- @param content table of the form
-- { ["zh-cn"]='foobar', ["zh-tw"]='firecat', ["zh-hk"]='' }
-- @returns string
-- "-{zh-cn:foobar;zh-tw:firecat;zh-hk:<span></span>}-"
--
-- @fixme allow for generating output without "-{" "}-", so that
-- it can be used with the last three wrappers.
function p.selective( content )
local text = '-{'
for variant, value in pairs( content ) do
if value == '' then
value = '<span></span>'
end
text = text .. variant .. ':' .. value .. ';'
end
text = text .. '}-'
return text
end
--- Write some text with a limited set of variants to convert to
--
-- @param content text to be written
-- @param variant a variant (string), or a list of variants
-- (semicolon-deliminated string, or table of strings)
-- @param[opt] force convert even under "zh" (no conversion) locale
function p.converted( content, variant, force )
if type( variant ) == 'table' then
variant = table.concat( variant, ';' )
end
return '-{' .. ( force and '' or 'zh;' ) .. variant .. '|' .. content .. '}-'
end
--- Wraps some "raw text" to not convert.
--
-- @fixme Is the "R" flag some undocumented/undefined no-op magic?
-- Are we using it instead of the old '-{' .. content .. '}-'
-- to avoid confusion caused by a flag in the "content"?
function p.raw( content )
return '-{R|' .. content .. '}-'
end
--- Wraps a title conversion rule.
function p.title( content )
return '-{T|' .. content .. '}-'
end
--- Wraps a (hidden) conversion rule definition.
function p.hidden( content )
return '-{H|' .. content .. '}-'
end
return p
76127574463fdd2329adddcc73f9a0f6b1aa12ea
Module:CGroup/core
828
128
253
252
2024-08-02T10:54:50Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.Item(o, r)
-- See [[那艺娜维基:字詞轉換處理/公共轉換組]]
-- o: 原文。若無此屬性,應使用nil而非空字串('')。
-- r: 用於全文轉換的規則,必填。
return { type = 'item', original = o, rule = r };
end
return p
97c445f7e3f780f771b528f0f42a6367ba48b2de
Module:Crc32lua
828
129
255
254
2024-08-02T10:54:51Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[
LUA MODULE
digest.crc32 - CRC-32 checksum implemented entirely in Lua.
SYNOPSIS
local CRC = require 'digest.crc32lua'
print(CRC.crc32 'test') --> 0xD87F7E0C or -662733300
assert(CRC.crc32('st', CRC.crc32('te')) == CRC.crc32 'test')
DESCRIPTION
This can be used to compute CRC-32 checksums on strings.
This is similar to [1-2].
API
Note: in the functions below, checksums are 32-bit integers stored in
numbers. The number format currently depends on the bit
implementation--see DESIGN NOTES below.
CRC.crc32_byte(byte [, crc]) --> rcrc
Returns CRC-32 checksum `rcrc` of byte `byte` (number 0..255) appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32_string(s, crc) --> bcrc
Returns CRC-32 checksum `rcrc` of string `s` appended to
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
if omitted.
CRC.crc32(o, crc) --> bcrc
This invokes `crc32_byte` if `o` is a byte or `crc32_string` if `o`
is a string.
CRC.bit
This contains the underlying bit library used by the module. It
should be considered a read-only copy.
DESIGN NOTES
Currently, this module exposes the underlying bit array implementation in CRC
checksums returned. In BitOp, bit arrays are 32-bit signed integer numbers
(may be negative). In Lua 5.2 'bit32' and 'bit.numberlua', bit arrays are
32-bit unsigned integer numbers (non-negative). This is subject to change
in the future but is currently done due to (unconfirmed) performance
implications.
On platforms with 64-bit numbers, one way to normalize CRC
checksums to be unsigned is to do `crcvalue % 2^32`,
The name of this module is inspired by Perl `Digest::CRC*`.
DEPENDENCIES
Requires one of the following bit libraries:
BitOp "bit" -- bitop.luajit.org -- This is included in LuaJIT and also available
for Lua 5.1/5.2. This provides the fastest performance in LuaJIT.
Lua 5.2 "bit32" -- www.lua.org/manual/5.2 -- This is provided in Lua 5.2
and is preferred in 5.2 (unless "bit" also happens to be installed).
"bit.numberlua" (>=000.003) -- https://github.com/davidm/lua-bit-numberlua
This is slowest and used as a last resort.
It is only a few times slower than "bit32" though.
DOWNLOAD/INSTALLATION
If using LuaRocks:
luarocks install lua-digest-crc32lua
Otherwise, download <https://github.com/davidm/lua-digest-crc32lua/zipball/master>.
Alternately, if using git:
git clone git://github.com/davidm/lua-digest-crc32lua.git
cd lua-digest-crc32lua
Optionally unpack:
./util.mk
or unpack and install in LuaRocks:
./util.mk install
REFERENCES
[1] http://www.axlradius.com/freestuff/CRC32.java
[2] http://www.gamedev.net/reference/articles/article1941.asp
[3] http://java.sun.com/j2se/1.5.0/docs/api/java/util/zip/CRC32.html
[4] http://www.dsource.org/projects/tango/docs/current/tango.io.digest.Crc32.html
[5] http://pydoc.org/1.5.2/zlib.html#-crc32
[6] http://www.python.org/doc/2.5.2/lib/module-binascii.html
LICENSE
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
(end license)
--]]
local M = {_TYPE='module', _NAME='digest.crc32', _VERSION='0.3.20111128'}
local type = type
local require = require
local setmetatable = setmetatable
--[[
Requires the first module listed that exists, else raises like `require`.
If a non-string is encountered, it is returned.
Second return value is module name loaded (or '').
--]]
local function requireany(...)
local errs = {}
for _,name in ipairs{...} do
if type(name) ~= 'string' then return name, '' end
local ok, mod = pcall(require, name)
if ok then return mod, name end
errs[#errs+1] = mod
end
error(table.concat(errs, '\n'), 2)
end
local bit, name_ = requireany('bit32', 'bit', 'bit.numberlua')
local bxor = bit.bxor
local bnot = bit.bnot
local band = bit.band
local rshift = bit.rshift
-- CRC-32-IEEE 802.3 (V.42)
local POLY = 0xEDB88320
-- Memoize function pattern (like http://lua-users.org/wiki/FuncTables ).
local function memoize(f)
local mt = {}
local t = setmetatable({}, mt)
function mt:__index(k)
local v = f(k); t[k] = v
return v
end
return t
end
-- CRC table.
local crc_table = memoize(function(i)
local crc = i
for _=1,8 do
local b = band(crc, 1)
crc = rshift(crc, 1)
if b == 1 then crc = bxor(crc, POLY) end
end
return crc
end)
function M.crc32_byte(byte, crc)
crc = bnot(crc or 0)
local v1 = rshift(crc, 8)
local v2 = crc_table[bxor(crc % 256, byte)]
return bnot(bxor(v1, v2))
end
local M_crc32_byte = M.crc32_byte
function M.crc32_string(s, crc)
crc = crc or 0
for i=1,#s do
crc = M_crc32_byte(s:byte(i), crc)
end
return crc
end
local M_crc32_string = M.crc32_string
function M.crc32(s, crc)
if type(s) == 'string' then
return M_crc32_string(s, crc)
else
return M_crc32_byte(s, crc)
end
end
M.bit = bit -- bit library used
return M
516bb70cd6815ac4a27c60f6bd63a90d26581f95
Module:Infobox
828
130
257
256
2024-08-02T10:54:51Z
黑茶
2
导入1个版本
Scribunto
text/plain
--
-- This module implements {{Infobox}}
-- 中文的此模块对比英文维基多解析了overimage, overcaption,
-- overimagerowclass以及header/labal/data*style参数。
--
local p = {}
local navbar = require('Module:Navbar')._navbar
local args = {}
local origArgs = {}
local root
local function notempty( s ) return s and s:match( '%S' ) end
local function fixChildBoxes(sval, tt)
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- the next two lines add a newline at the end of lists for the PHP parser
-- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&oldid=849054481
-- remove when [[:phab:T191516]] is fixed or OBE
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1')
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1')
return s
else
return sval
end
end
local function union(t1, t2)
-- Returns the union of the values of two tables, as a sequence.
local vals = {}
for k, v in pairs(t1) do
vals[v] = true
end
for k, v in pairs(t2) do
vals[v] = true
end
local ret = {}
for k, v in pairs(vals) do
table.insert(ret, k)
end
return ret
end
local function getArgNums(prefix)
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix was 'data', and
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local nums = {}
for k, v in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end
local function addRow(rowArgs)
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
if rowArgs.header and rowArgs.header ~= '_BLANK_' then
root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(rowArgs.rowstyle)
:attr('id', rowArgs.rowid)
:tag('th')
:attr('colspan', 2)
:attr('id', rowArgs.headerid)
:addClass(rowArgs.class)
:addClass(args.headerclass)
:css('text-align', 'center')
:cssText(rowArgs.headerstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.header, 'th'))
if rowArgs.data then
root:wikitext('[[Category:使用已忽略数据行信息框模板的条目]]')
end
elseif rowArgs.data then
if not rowArgs.data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then
rowArgs.rowstyle = 'display:none'
end
local row = root:tag('tr')
row:addClass(rowArgs.rowclass)
row:cssText(rowArgs.rowstyle)
row:attr('id', rowArgs.rowid)
if rowArgs.label then
row
:tag('th')
:attr('scope', 'row')
:css('text-align', 'left')
:attr('id', rowArgs.labelid)
:cssText(rowArgs.labelstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end
local dataCell = row:tag('td')
if not rowArgs.label then
dataCell
:attr('colspan', 2)
:css('text-align', 'center')
end
dataCell
:attr('id', rowArgs.dataid)
:addClass(rowArgs.class)
:cssText(rowArgs.datastyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.data, 'td'))
end
end
local function renderOverImage()
if not args.overimage then return end
local row = root:tag('tr')
row:addClass(args.overimagerowclass)
local topImage = row:tag('td')
topImage:attr('colspan', 2)
topImage:addClass(args.imageclass)
topImage:cssText(args.imagestyle)
topImage:css('text-align', 'center')
if args.overcaption and args.captionstyle then
topImage:wikitext(fixChildBoxes(args.overimage .. '<div style=\"' .. args.captionstyle .. '\">' .. args.overcaption .. '</div>', 'td'))
else
if args.overcaption then
topImage:wikitext(fixChildBoxes(args.overimage .. '<div>' .. args.overcaption .. '</div>', 'td'))
else
topImage:wikitext(fixChildBoxes(args.overimage, 'td'))
end
end
end
local function renderTitle()
if not args.title then return end
root
:tag('caption')
:addClass(args.titleclass)
:cssText(args.titlestyle)
:wikitext('\'\'\'' .. args.title .. '\'\'\'')
end
local function renderAboveRow()
if not args.above then return end
root
:tag('tr')
:tag('th')
:attr('colspan', 2)
:addClass(args.aboveclass)
:css('text-align', 'center')
:css('font-size', '125%')
:css('font-weight', 'bold')
:cssText(args.abovestyle)
:wikitext(fixChildBoxes(args.above,'th'))
end
local function renderBelowRow()
if not args.below then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass(args.belowclass)
:css('text-align', 'center')
:cssText(args.belowstyle)
:wikitext(fixChildBoxes(args.below,'td'))
end
local function renderSubheaders()
if args.subheader then
args.subheader1 = args.subheader
end
if args.subheaderrowclass then
args.subheaderrowclass1 = args.subheaderrowclass
end
local subheadernums = getArgNums('subheader')
for k, num in ipairs(subheadernums) do
addRow({
data = args['subheader' .. tostring(num)],
datastyle = args.subheaderstyle,
rowcellstyle = args['subheaderstyle' .. tostring(num)],
class = args.subheaderclass,
rowclass = args['subheaderrowclass' .. tostring(num)]
})
end
end
local function renderImages()
if args.image then
args.image1 = args.image
end
if args.caption then
args.caption1 = args.caption
end
local imagenums = getArgNums('image')
for k, num in ipairs(imagenums) do
local caption = args['caption' .. tostring(num)]
local data = mw.html.create():wikitext(args['image' .. tostring(num)])
if caption then
data
:tag('div')
:cssText(args.captionstyle)
:wikitext(caption)
end
addRow({
data = tostring(data),
datastyle = args.imagestyle,
class = args.imageclass,
rowclass = args['imagerowclass' .. tostring(num)]
})
end
end
local function preprocessRows()
-- Gets the union of the header and data argument numbers,
-- and renders them all in order using addRow.
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
local lastheader
for k, num in ipairs(rownums) do
if args['header' .. tostring(num)] then
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
lastheader = num
elseif args['data' .. tostring(num)] and args['data' .. tostring(num)]:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then
local data = args['data' .. tostring(num)]
if data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('%S') then
lastheader = nil
end
end
end
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
end
local function renderRows()
-- Gets the union of the header and data argument numbers,
-- and renders them all in order using addRow.
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
for k, num in ipairs(rownums) do
addRow({
header = args['header' .. tostring(num)],
headerstyle = (args.headerstyle or '') .. (args.headerstyle and ';' or '') .. (args['header' .. tostring(num) .. 'style'] or ''),
label = args['label' .. tostring(num)],
labelstyle = (args.labelstyle or '') .. (args.labelstyle and ';' or '') .. (args['label' .. tostring(num) .. 'style'] or ''),
data = args['data' .. tostring(num)],
datastyle = (args.datastyle or '') .. (args.datastyle and ';' or '') .. (args['data' .. tostring(num) .. 'style'] or ''),
class = args['class' .. tostring(num)],
rowclass = args['rowclass' .. tostring(num)],
rowstyle = args['rowstyle' .. tostring(num)],
rowcellstyle = args['rowcellstyle' .. tostring(num)],
dataid = args['dataid' .. tostring(num)],
labelid = args['labelid' .. tostring(num)],
headerid = args['headerid' .. tostring(num)],
rowid = args['rowid' .. tostring(num)]
})
end
end
local function renderNavBar()
if not args.name then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:css('text-align', 'right')
:wikitext(navbar{
args.name,
mini = 1,
})
end
local function renderItalicTitle()
local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'italic title'}))
end
end
local function renderTrackingCategories()
if args.decat ~= 'yes' then
if args.child == 'yes' then
if args.title then
root:wikitext('[[Category:使用带有标题参数的嵌入式信息框模板的条目]]')
end
elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
root:wikitext('[[Category:使用无数据行信息框模板的条目]]')
end
end
end
local function _infobox()
-- Specify the overall layout of the infobox, with special settings
-- if the infobox is used as a 'child' inside another infobox.
if args.child ~= 'yes' then
root = mw.html.create('table')
root
:addClass((args.subbox ~= 'yes') and 'infobox' or nil)
:addClass(args.bodyclass)
:attr('cellspacing', 3)
:css('border-spacing', '3px')
if args.subbox == 'yes' then
root
:css('padding', '0')
:css('border', 'none')
:css('margin', '-3px')
:css('width', 'auto')
:css('min-width', '100%')
:css('font-size', '88%')
:css('clear', 'none')
:css('float', 'none')
:css('background-color', 'transparent')
:css('color', 'inherit')
else
root
:css('width', '22em')
:css('text-align', 'left')
:css('font-size', '88%')
:css('line-height', '1.5em')
end
root
:cssText(args.bodystyle)
renderTitle()
renderAboveRow()
else
root = mw.html.create()
root
:wikitext(args.title)
end
renderOverImage()
renderSubheaders()
renderImages()
if args.autoheaders then
preprocessRows()
end
renderRows()
renderBelowRow()
renderNavBar()
renderItalicTitle()
renderTrackingCategories()
return tostring(root)
end
local function preprocessSingleArg(argName)
-- If the argument exists and isn't blank, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
if origArgs[argName] and origArgs[argName] ~= '' then
args[argName] = origArgs[argName]
end
end
local function preprocessArgs(prefixTable, step)
-- Assign the parameters with the given prefixes to the args table, in order, in batches
-- of the step size specified. This is to prevent references etc. from appearing in the
-- wrong order. The prefixTable should be an array containing tables, each of which has
-- two possible fields, a "prefix" string and a "depend" table. The function always parses
-- parameters containing the "prefix" string, but only parses parameters in the "depend"
-- table if the prefix parameter is present and non-blank.
if type(prefixTable) ~= 'table' then
error("Non-table value detected for the prefix table", 2)
end
if type(step) ~= 'number' then
error("Invalid step value detected", 2)
end
-- Get arguments without a number suffix, and check for bad input.
for i,v in ipairs(prefixTable) do
if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
error('Invalid input detected to preprocessArgs prefix table', 2)
end
preprocessSingleArg(v.prefix)
-- Only parse the depend parameter if the prefix parameter is present and not blank.
if args[v.prefix] and v.depend then
for j, dependValue in ipairs(v.depend) do
if type(dependValue) ~= 'string' then
error('Invalid "depend" parameter value detected in preprocessArgs')
end
preprocessSingleArg(dependValue)
end
end
end
-- Get arguments with number suffixes.
local a = 1 -- Counter variable.
local moreArgumentsExist = true
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a, a + step - 1 do
for j,v in ipairs(prefixTable) do
local prefixArgName = v.prefix .. tostring(i)
if origArgs[prefixArgName] then
moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
preprocessSingleArg(prefixArgName)
end
-- Process the depend table if the prefix argument is present and not blank, or
-- we are processing "prefix1" and "prefix" is present and not blank, and
-- if the depend table is present.
if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
for j,dependValue in ipairs(v.depend) do
local dependArgName = dependValue .. tostring(i)
preprocessSingleArg(dependArgName)
end
end
end
end
a = a + step
end
end
function preprocessSpecificStyle(styleTable, step)
-- Assign the parameters *style to the args table
local a = 1 -- Counter variable.
local moreArgumentsExist = true
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a,a + step - 1 do
for j,v in ipairs(styleTable) do
local styleArgName = v.arg .. tostring(i) .. 'style'
if origArgs[styleArgName] then
moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
preprocessSingleArg(styleArgName)
end
end
end
a = a + step
end
end
local function parseDataParameters()
-- Parse the data parameters in the same order that the old {{infobox}} did, so that
-- references etc. will display in the expected places. Parameters that depend on
-- another parameter are only processed if that parameter is present, to avoid
-- phantom references appearing in article reference lists.
preprocessSingleArg('autoheaders')
preprocessSingleArg('child')
preprocessSingleArg('bodyclass')
preprocessSingleArg('subbox')
preprocessSingleArg('bodystyle')
preprocessSingleArg('overimage')
preprocessSingleArg('overcaption')
preprocessSingleArg('overimagerowclass')
preprocessSingleArg('title')
preprocessSingleArg('titleclass')
preprocessSingleArg('titlestyle')
preprocessSingleArg('above')
preprocessSingleArg('aboveclass')
preprocessSingleArg('abovestyle')
preprocessArgs({
{prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}
}, 10)
preprocessSingleArg('subheaderstyle')
preprocessSingleArg('subheaderclass')
preprocessArgs({
{prefix = 'image', depend = {'caption', 'imagerowclass'}}
}, 10)
preprocessSingleArg('captionstyle')
preprocessSingleArg('imagestyle')
preprocessSingleArg('imageclass')
preprocessArgs({
{prefix = 'header'},
{prefix = 'data', depend = {'label'}},
{prefix = 'rowclass'},
{prefix = 'rowstyle'},
{prefix = 'rowcellstyle'},
{prefix = 'class'},
{prefix = 'dataid'},
{prefix = 'labelid'},
{prefix = 'headerid'},
{prefix = 'rowid'}
}, 80)
preprocessSpecificStyle({
{arg = 'header'},
{arg = 'label'},
{arg = 'data'}
}, 80)
preprocessSingleArg('headerclass')
preprocessSingleArg('headerstyle')
preprocessSingleArg('labelstyle')
preprocessSingleArg('datastyle')
preprocessSingleArg('below')
preprocessSingleArg('belowclass')
preprocessSingleArg('belowstyle')
preprocessSingleArg('name')
args['italic title'] = origArgs['italic title'] -- different behaviour if blank or absent
preprocessSingleArg('decat')
end
function p.infobox(frame)
-- If called via #invoke, use the args passed into the invoking template.
-- Otherwise, for testing purposes, assume args are being passed directly in.
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end
parseDataParameters()
return _infobox()
end
function p.infoboxTemplate(frame)
-- For calling via #invoke within a template
origArgs = {}
for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end
parseDataParameters()
return _infobox()
end
return p
b1241aab87afb6394aa68f97f9f73cef0fa25fa0
Template:Clear
10
131
259
258
2024-08-02T10:54:52Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div style="clear:{{{1|both}}};"></div><noinclude>{{documentation}}</noinclude>
2d3fa80e4576702b6379930ebc3617f6d10e4346
Template:Template other
10
132
261
260
2024-08-02T10:54:54Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{lc: {{{demospace}}} }} <!--Use lower case "demospace"-->
| {{#ifeq:{{NAMESPACE}}|{{ns:Template}}
| template
| other
}}
}}
| template = {{{1|}}}
| other
| #default = {{{2|}}}
}}<!--End switch--><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
06fb13d264df967b5232141067eb7d2b67372d76
Module:Documentation
828
97
263
189
2024-08-02T10:54:56Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[那艺娜维基:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[那艺娜维基:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[那艺娜维基:Template documentation|documentation]]
-- is [[那艺娜维基:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[那艺娜维基:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2c374c042ebd8bc4d2d63d207aa078459069c065
Module:Documentation/config
828
98
265
191
2024-08-02T10:54:56Z
黑茶
2
导入1个版本
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[那艺娜维基:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[那艺娜维基:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[那艺娜维基:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
c0991af7f04ef8f2b12d94f64d2e0ea5968d2413
Module:CGroup/IT
828
133
267
266
2024-08-02T10:54:56Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- 用法: Item('原文', '轉換規則')
local Item = require('Module:CGroup/core').Item;
return {
name = 'IT',
description = '-{zh-cn:信息技术; zh-sg:资讯科技; zh-my:资讯科技; zh-tw:資訊科技;}-',
content = {
{ type = 'text', text = [=[
== A ==
]=] },
Item('AI', 'zh-cn:人工智能; zh-sg:人工智慧; zh-tw:人工智慧; zh-hk:人工智能;'),
-- 容易過度轉換,僅單向轉換
Item('access', '存取=>zh-cn:访问; 存取=>zh-tw:存取;'),
Item('access', '存取權=>zh-cn:访问权; 存取權=>zh-tw:存取權;'),
Item('access', '访问权=>zh-cn:访问权; 访问权=>zh-tw:存取權;'),
Item('access', '存取權限=>zh-cn:访问权限; 存取權限=>zh-tw:存取權限;'),
Item('access', '访问权限=>zh-cn:访问权限; 访问权限=>zh-tw:存取權限;'),
Item('access control list', 'zh-cn:访问控制表; zh-tw:存取控制列表;'),
Item('access control list', '存取控制串列=>zh-cn:访问控制表; 存取控制串列=>zh-sg:访问控制表; 存取控制串列=>zh-my:访问控制表; zh-tw:存取控制列表;'),
Item('access Multiplexer', 'zh-cn:接入复用器; zh-tw:接取多工器;'),
Item('access Point', 'zh-cn:接入点; zh-tw:存取點;'),
Item('account', 'zh-cn:账号; zh-tw:帳號; zh-hk:帳號;'),
Item('account', 'zh-cn:账户; zh-tw:帳戶; zh-hk:帳戶;'),
Item('activation', 'zh-cn:激活; zh-tw:啟用;'),
Item('activation function', 'zh-cn:激活函数; zh-tw:啟用功能;'),
Item('adapter', 'zh-cn:适配器; zh-tw:配接器;'),
Item('add-on', 'zh-cn:附加组件; zh-tw:附加元件;'),
Item('address', 'zh-cn:地址; zh-tw:位址; zh-hk:地址;'),
Item('address bar', 'zh-cn:地址栏; zh-tw:網址列; zh-hk:地址列;'),
Item('addressing', 'zh-cn:寻址; zh-tw:定址; zh-hk:定址;'),
Item('addressing modes', 'zh-cn:寻址模式; zh-tw:定址模式; zh-hk:定址模式;'),
Item('advanced', 'zh-cn:高级; zh-tw:進階;'),
Item('advertising area', 'zh-cn:广告位; zh-tw:廣告區;'),
Item('agent-oriented programming', 'zh-cn:面向代理编程; zh-tw:代理人導向程式設計;'),
Item('album (online)', 'zh-cn:相册; zh-my:相簿; zh-tw:相簿;'),
Item('algorithm', 'zh-cn:算法; zh-tw:演算法;'),
Item('allocation unit', 'zh-cn:分配单元; zh-tw:單位配置;'),
Item('analog', 'zh-cn:模拟; zh-tw:類比; zh-hk:模擬;'),
Item('analog broadcasting', 'zh-cn:模拟广播; zh-tw:類比廣播; zh-hk:模擬廣播;'),
Item('analog television', 'zh-cn:模拟电视; zh-tw:類比電視; zh-hk:模擬電視;'),
-- 港台的「殺毒」有時有「清除病毒」的意思
Item('antivirus', 'zh-cn:杀毒; zh-tw:防毒;'),
Item('AOL', 'zh:美國在線; zh-cn:美国在线; zh-tw:美國線上;'),
Item('application', 'zh:應用程序; zh-cn:应用程序; zh-my:应用程式; zh-hant:應用程式;'),
Item('application programming interface', 'zh:應用程序接口; zh-cn:应用程序接口; zh:应用程式介面; zh-tw:應用程式介面;'),
Item('archive', 'zh:壓縮包; zh-cn:压缩包; zh-my:压缩档; zh-tw:壓縮檔;'),
Item('array (RAID)', 'zh-cn:服务器阵列; zh-sg:伺服器阵列; zh-tw:伺服器陣列;'),
Item('array (RAID)', 'zh-cn:硬盘阵列; zh-tw:硬碟陣列;'),
Item('array (RAID)', 'zh-cn:磁盘阵列; zh-tw:磁碟陣列;'),
Item('array (RAID)', 'zh-cn:阵列服务器; zh-sg:阵列伺服器; zh-tw:陣列伺服器;'),
Item('array (RAID)', 'zh-cn:阵列硬盘; zh-tw:陣列硬碟;'),
Item('array', 'zh-cn:数组; zh-tw:陣列;'),
Item('Artificial Neural', 'zh:人工神經; zh-cn:人工神经; zh-tw:類神經;'),
Item('assembler', 'zh-cn:汇编; zh-tw:組譯;'),
Item('Assembly language', 'zh-cn:汇编语言; zh-tw:組合語言; zh-hk:匯編語言;'),
Item('assembly mnemonic', 'zh-cn:助记符; zh-tw:輔助記憶碼;'),
Item('assignment operator', 'zh-cn:赋值运算符; zh-tw:設定運算子;'),
Item('assignment operator', '賦值運算符=>zh-tw:設定運算子; 賦值運算符=>zh-hk:設定運算子; 賦值運算符=>zh-mo:設定運算子;'),
Item('assignment operator', '赋值操作符=>zh-tw:設定運算子; 赋值操作符=>zh-hk:設定運算子; 赋值操作符=>zh-mo:設定運算子;'),
Item('assignment operator', '賦值操作符=>zh-tw:設定運算子; 賦值操作符=>zh-hk:設定運算子; 賦值操作符=>zh-mo:設定運算子;'),
Item('asynchrony', 'zh-cn:异步; zh-tw:非同步;'),
Item('asynchrony', '異步=>zh-tw:非同步; 異步=>zh-hk:非同步; 異步=>zh-mo:非同步;'),
Item('average bitrate', 'zh-cn:平均码率; zh-tw:平均位元速率;'),
Item('audio', 'zh-cn:音频; zh-tw:音訊; zh-hk:音頻;'),
Item('audio track', 'zh-cn:音频轨; zh-tw:音訊軌; zh-hk:音頻軌;'),
Item('audio input', 'zh-cn:音频输入; zh-tw:音訊輸入; zh-hk:音頻輸入;'),
Item('audio output', 'zh-cn:音频输出; zh-tw:音訊輸出; zh-hk:音頻輸出;'),
Item('audio file', 'zh-cn:音频文件; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio file', 'zh-cn:音频文档; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio file', 'zh-cn:音频档; zh-tw:音訊檔; zh-hk:音頻檔;'),
Item('audio profiles', 'zh-cn:情景模式; zh-tw:音訊設定檔;'),
Item('audit', 'zh-cn:审核; zh-tw:稽核;'),
Item('augmented reality', 'zh:增強現實; zh-cn:增强现实; zh-sg:扩增实境; zh-tw:擴增實境; zh-hk:擴張實境;'),
{ type = 'text', text = [[
== B ==
]] },
Item('back chaining', 'zh-cn:反链接; zh-tw:反鏈結;'),
Item('background traffic', 'zh-cn:后台流量; zh-tw:背景流量;'),
Item('backward compatible', '向后兼容=>zh-tw:向下相容; 向后兼容=>zh-hk:向下相容; 向后兼容=>zh-mo:向下相容;'),
Item('backward compatible', '向後兼容=>zh-tw:向下相容; 向後兼容=>zh-hk:向下相容; 向後兼容=>zh-mo:向下相容;'),
Item('bad sector', 'zh-cn:坏道; zh-tw:壞軌;'),
Item('band width', 'zh-cn:带宽; zh-tw:頻寬;'),
Item('base class', 'zh-cn:基类; zh-tw:基礎類別;'),
Item('base name', 'zh-cn:文件主名; zh-tw:主檔名;'),
Item('base type', 'zh-cn:基类型; zh-tw:基本類型;'),
Item('baseband', 'zh-cn:基带; zh-hk:基帶; zh-tw:基頻;'),
Item('batch', 'zh-cn:批量; zh-tw:批次;'),
Item('batch', 'zh-cn:批处理; zh-tw:批次處理;'),
Item('batch file', 'zh-cn:批处理文件; zh-tw:批次檔;'),
Item('batch programs', 'zh-cn:批处理程序; zh-tw:批次程式;'),
Item('Berkeley Software Distribution', 'zh-cn:伯克利软件套件; zh-tw:柏克萊軟體套件; zh-hk:柏克萊軟件套件;'),
Item('big data', 'zh-cn:大数据; zh-tw:大數據;'),
Item('Bill Gates', 'zh-cn:盖茨; zh-tw:蓋茲; zh-hk:蓋茨;'),
Item('binary', '二叉=>zh-tw:二元; 二叉=>zh-hk:二元; 二叉=>zh-mo:二元;'),
Item('binary function', 'zh-cn:双参函数; zh-tw:二元函數;'),
Item('binary heap', 'zh-cn:二叉堆; zh-tw:二元堆積; zh-hk:二叉堆積;'),
Item('binary linked list', 'zh-cn:二叉链表; zh-tw:二元連結串列;'),
Item('binary linked list', '二叉鏈表=>zh-tw:二元連結串列; 二叉鏈表=>zh-hk:二元連結串列; 二叉鏈表=>zh-mo:二元連結串列;'),
Item('binary search tree', 'zh-cn:二叉搜索树; zh-tw:二元搜尋樹; zh-hk:二叉搜尋樹;'),
Item('binary search tree', '二叉查找树=>zh-tw:二元搜尋樹; 二叉查找树=>zh-hk:二叉搜尋樹; 二叉查找树=>zh-mo:二叉搜尋樹;'),
Item('binary tree', 'zh-cn:二叉树; zh-tw:二元樹; zh-hk:二叉樹;'),
Item('binding', 'zh-cn:绑定; zh-tw:繫結;'),
Item('bit', 'zh-cn:比特; zh-sg:位元; zh-tw:位元;'),
Item('bit', '二进制位=>zh-sg:位元; 二进制位=>zh-my:位元; 二进制位=>zh-tw:位元; 二进制位=>zh-hk:位元; 二进制位=>zh-mo:位元;'),
Item('bit (4-bit)', 'zh-cn:4位; zh-tw:4位元;'),
Item('bit (8-bit)', 'zh-cn:8位; zh-tw:8位元;'),
-- 有可能過度轉換,編輯時須注意
Item('bit (12-bit)', 'zh-cn:12位; zh-tw:12位元;'),
Item('bit (16-bit)', 'zh-cn:16位; zh-tw:16位元;'),
Item('bit (18-bit)', 'zh-cn:18位; zh-tw:18位元;'),
Item('bit (24-bit)', 'zh-cn:24位; zh-tw:24位元;'),
Item('bit (31-bit)', 'zh-cn:31位; zh-tw:31位元;'),
Item('bit (32-bit)', 'zh-cn:32位; zh-tw:32位元;'),
Item('bit (36-bit)', 'zh-cn:36位; zh-tw:36位元;'),
Item('bit (48-bit)', 'zh-cn:48位; zh-tw:48位元;'),
Item('bit (60-bit)', 'zh-cn:60位; zh-tw:60位元;'),
Item('bit (64-bit)', 'zh-cn:64位; zh-tw:64位元;'),
Item('bit (80-bit)', 'zh-cn:80位; zh-tw:80位元;'),
Item('bit (128-bit)', 'zh-cn:128位; zh-tw:128位元;'),
Item('bit error rate', 'zh-cn:比特误码率; zh-tw:位元錯誤率;'),
Item('bit error rate', '误比特率=>zh-tw:位元錯誤率; 误比特率=>zh-hk:位元錯誤率; 误比特率=>zh-mo:位元錯誤率;'),
Item('bit field', 'zh-cn:位段; zh-tw:位元欄;'),
Item('bit pattern', 'zh-cn:位模式; zh-tw:位元型樣;'),
Item('bit pattern', '位元模式=>zh-cn:位模式; 位元模式=>zh-sg:位模式; 位元模式=>zh-my:位模式;'),
Item('bit string', 'zh-cn:位串; zh-tw:位元串;'),
Item('Bitmap', '栅格图=>zh-tw:點陣圖;'),
Item('Bitmap', 'zh-cn:位图; zh-tw:點陣圖;'),
Item('bitrate', 'zh-cn:比特率; zh-tw:位元速率;'),
Item('bitrate', '码率=>zh-tw:位元速率; 码率=>zh-hk:位元速率; 码率=>zh-mo:位元速率;'),
Item('bitrate', '碼率=>zh-tw:位元速率; 碼率=>zh-hk:位元速率; 碼率=>zh-mo:位元速率;'),
Item('bitrate', '荷码率=>zh-tw:位元速率; 荷码率=>zh-hk:位元速率; 荷码率=>zh-mo:位元速率;'),
Item('bitrate', '荷碼率=>zh-tw:位元速率; 荷碼率=>zh-hk:位元速率; 荷碼率=>zh-mo:位元速率;'),
Item('bitwise', 'zh-cn:按位; zh-tw:按位元;'),
Item('bitwise operation', 'zh-cn:位操作; zh-tw:位元運算;'),
Item('bitwise operation', '位元运算=>zh-cn:位操作; 位元运算=>zh-sg:位操作; 位元运算=>zh-my:位操作;'),
Item('bitwise operation', '位元操作=>zh-cn:位操作; 位元操作=>zh-sg:位操作; 位元操作=>zh-my:位操作;'),
Item('bitwise operation', '位运算=>zh-tw:位元運算; 位运算=>zh-hk:位元運算; 位运算=>zh-mo:位元運算;'),
Item('bitwise operation', '位運算=>zh-tw:位元運算; 位運算=>zh-hk:位元運算; 位運算=>zh-mo:位元運算;'),
Item('black box testing', 'zh-cn:黑盒测试; zh-tw:黑箱測試;'),
Item('Blade Server', 'zh-cn:刀片服务器; zh-tw:刀鋒伺服器;'),
Item('blank screen', 'zh-cn:黑屏; zh-tw:黑畫面;'),
Item('block', 'zh-cn:屏蔽; zh-tw:封鎖;'),
Item('block (Unicode)', '区段=>zh-cn:区块; 区段=>zh-sg:区块; 区段=>zh-my:区块;'),
Item('block chaining', 'zh-cn:组链接; zh-tw:塊鏈結;'),
Item('block chaining', 'zh-cn:区块链接; zh-tw:區塊鏈結;'),
Item('block cipher', 'zh-cn:分组密码; zh-tw:區塊加密法;'),
Item('block diagram', 'zh-cn:框图; zh-tw:方塊圖;'),
Item('blog', 'zh-cn:博客; zh-tw:部落格; zh-hk:網誌; zh-my:部落格;'),
Item('bluetooth', '藍芽=>zh-hans:蓝牙; 藍芽=>zh-hant:藍牙; 藍芽=>zh-cn:蓝牙; 藍芽=>zh-tw:藍牙; 藍芽=>zh-hk:藍牙;'),
Item('bluetooth', '蓝芽=>zh-hans:蓝牙; 蓝芽=>zh-hant:藍牙; 蓝芽=>zh-cn:蓝牙; 蓝芽=>zh-tw:藍牙; 蓝芽=>zh-hk:藍牙;'),
Item('Blue Screen', 'zh-hant:藍屏; zh-cn:蓝屏; zh-tw:藍白畫面; zh-hk:藍畫面;'),
Item('Blue Screen of Death', 'zh-hant:藍屏死機; zh-cn:蓝屏死机; zh-tw:藍白當機; zh-hk:藍畫面死機;'),
Item('boot disk', 'zh-cn:启动盘; zh-tw:啟動磁碟;'),
Item('boot loader', 'zh-cn:启动引导程序; zh-tw:啟動載入程式;'),
Item('bottom-up', 'zh-cn:自底向上; zh-tw:由下而上;'),
Item('Boyce-Codd normal form', 'zh-cn:BC范式; zh-tw:BC正規形式;'),
Item('brain-machine interface', 'zh-cn:脑机接口; zh-my:脑机介面; zh-tw:人機介面;'),
Item('Broadband', 'zh:寬帶; zh-cn:宽带; zh-my:宽频; zh-tw:寬頻;'),
Item('Bubble sort', 'zh-cn:冒泡排序; zh-tw:泡沫排序;'),
Item('buffer', 'zh-cn:缓冲器; zh-tw:緩衝區;'),
Item('buffer overflow', 'zh-cn:缓存溢出; zh-tw:緩衝區溢位;'),
Item('bug', '隐错=>zh-tw:錯誤; 隐错=>zh-hk:錯誤; 隐错=>zh-mo:錯誤;'),
Item('build-in', 'zh:內置; zh-cn:内置; zh-sg:内建; zh-tw:內建;'),
Item('Built-in', '自带=>zh-tw:內建; 自带=>zh-hk:內建; 自带=>zh-mo:內建;'),
Item('Built-in', '自帶=>zh-tw:內建; 自帶=>zh-hk:內建; 自帶=>zh-mo:內建;'),
Item('burn', 'zh-cn:刻录; zh-tw:燒錄;'),
Item('Business Model', 'zh-cn:商业模型; zh-tw:商業模式;'),
Item('Bus', 'zh-cn:总线; zh-tw:匯流排; zh-hk:匯流排;'),
Item('byte', 'zh:字節; zh-cn:字节; zh-tw:位元組; zh-hk:位元組; zh-mo:位元組;'),
Item('boolean', 'zh-cn:布尔; zh-tw:布林;'),
Item('boolean algebra', 'zh-cn:布尔逻辑; zh-tw:布林運算;'),
Item('Boot Camp', 'zh-cn:启动转换; zh-tw:啟動切換; zh-hk:開機切換;'),
{ type = 'text', text = [[
== C ==
]] },
Item('cache', 'zh:緩存; zh-cn:缓存; zh-tw:快取; zh-hk:快取;'),
Item('cache memory', 'zh-cn:缓冲存储器; zh-tw:快取記憶體;'),
Item('cache memory', '缓冲存储器=>zh-hk:緩衝記憶體; 缓冲存储器=>zh-mo:緩衝記憶體;'),
Item('cache memory', '缓存器=>zh-tw:快取記憶體; 缓存器=>zh-hk:緩衝記憶體; 缓存器=>zh-mo:緩衝記憶體;'),
Item('cache memory', '快取記憶體=>zh-hk:緩衝記憶體; 快取記憶體=>zh-mo:緩衝記憶體;'),
Item('cache memory', 'zh-cn:高速缓冲存储器; zh-tw:高速緩衝記憶體;'),
Item('cache memory', '高速缓存=>zh-tw:高速緩衝記憶體; 高速缓存=>zh-hk:高速緩衝記憶體; 高速缓存=>zh-mo:高速緩衝記憶體;'),
Item('cached webpage', 'zh-cn:网页快照; zh-tw:頁庫存檔;'),
Item('calculator', 'zh-cn:计算器; zh-hk:計數機;'),
Item('calculator', '计算器=>zh-tw:計算機;'),
Item('calculator', '計數機=>zh-tw:計算機;'),
Item('calculator', '計算器=>zh-hk:計數機; 計算器=>zh-mo:計數機;'),
Item('calendar', '行事曆=>zh-cn:日历; 行事曆=>zh-sg:日历; 行事曆=>zh-my:日历;'),
Item('calendar program', 'zh-cn:日历程序; zh-tw:行事曆程式;'),
Item('call', 'zh-cn:调用; zh-tw:呼叫;'),
Item('Call Level Interface (CLI)', 'zh-cn:调用层接口; zh-tw:呼叫層級介面;'),
-- 回撥似乎用在電話比較多,計算機上回呼比較多。
Item('callback', 'zh-cn:回调; zh-tw:回呼;'),
Item('camcorder', 'zh-cn:摄像机; zh-tw:攝錄影機; zh-hk:攝像放像機;'),
Item('camera phone', 'zh-cn:照相手机; zh-tw:照相手機; zh-hk:相機手機;'),
Item('campus network', 'zh-cn:校园网; zh-tw:校園網路; zh-hk:校園網絡;'),
Item('campus network', '园区网络=>zh-tw:校園網路; 园区网络=>zh-hk:校園網絡; 园区网络=>zh-mo:校園網絡;'),
Item('capture', '捕获=>zh-tw:擷取; 捕获=>zh-hk:擷取; 捕获=>zh-mo:擷取;'),
Item('card reader', 'zh-cn:读卡器; zh-tw:讀卡機; zh-hk:讀卡器;'),
Item('carriage return character', 'zh-cn:回车符; zh-tw:回車字元;'),
Item('CDN', 'zh-cn:内容分发网络; zh-tw:內容傳遞網路;'),
Item('Cell', 'zh-cn:单元格; zh-tw:儲存格;'),
Item('Cellular data', 'zh-cn:蜂窝数据; zh-tw:蜂巢式資料; zh-hk:蜂巢式數據;'),
Item('Cellular network', 'zh-cn:蜂窝网络; zh-tw:蜂巢式網路; zh-hk:蜂巢式網絡;'),
Item('certificate', 'zh-cn:证书; zh-tw:憑證; zh-hk:證書;'),
Item('chain', '串鏈=>zh-cn:链; 串鏈=>zh-sg:链; 串鏈=>zh-my:链;'),
Item('chaining', '鍊接=>zh-cn:链接; 鍊接=>zh-sg:链接; 鍊接=>zh-my:链接;'),
Item('chaining backward', 'zh-cn:链接反向; zh-tw:鏈結反向;'),
Item('chaining forward', 'zh-cn:链接正向; zh-tw:鏈結正向;'),
Item('chaining of commands', 'zh-cn:命令链接; zh-tw:命令鏈結;'),
Item('chaining search', 'zh-cn:链接搜索; zh-tw:鏈結搜尋;'),
Item('channel', '渠道=>zh-tw:管道;'),
Item('character', 'zh-cn:字符; zh-tw:字元;'),
Item('character generator', 'zh-cn:字符生成器; zh-tw:字元產生器;'),
Item('character printer', 'zh-cn:字符打印机; zh-tw:字元列印機;'),
Item('check bit', 'zh-cn:检验位; zh-tw:核對位元;'),
Item('check button', 'zh-cn:复选按钮; zh-tw:核取按鈕;'),
Item('checkbox', 'zh-cn:复选框; zh-tw:核取方塊;'),
Item('checksum', 'zh-cn:检验和; zh-tw:核對和;'),
Item('Chief Executive Officer (CEO)', 'zh:首席執行官; zh-cn:首席执行官; zh-sg:行政总裁; zh-my:总执行长; zh-tw:執行長; zh-hk:行政總裁;'),
Item('Chief Information Officer (CIO)', 'zh-cn:首席信息官; zh-my:总资讯长; zh-tw:資訊長; zh-hk:資訊總監;'),
Item('Chief Operating Officer (COO)', 'zh:首席運營官; zh-cn:首席运营官; zh-my:总营运长; zh-tw:營運長; zh-hk:營運總監;'),
Item('Chief Technology Officer (CTO)', 'zh:首席技術官; zh-cn:首席技术官; zh-my:总技术长; zh-tw:技術長;'),
Item('child class', '子類別=>zh-cn:子类; 子類別=>zh-sg:子类; 子類別=>zh-my:子类;'),
Item('chip', 'zh-cn:芯片; zh-my:晶片; zh-tw:晶片;'),
Item('class constructor', 'zh-cn:类的构造函数; zh-tw:類別的建構函數;'),
Item('class constructor', '類別建構子=>zh-cn:类的构造函数; 類別建構子=>zh-sg:类的构造函数; 類別建構子=>zh-my:类的构造函数;'),
Item('class declaration', 'zh-cn:类声明; zh-tw:類別宣告;'),
Item('class definition', 'zh-cn:类定义; zh-tw:類別定義;'),
Item('class destructor', 'zh-cn:类的析构函数; zh-tw:類別的破壞函數;'),
Item('class destructor', '類別破壞子=>zh-cn:类的析构函数; 類別破壞子=>zh-sg:类的析构函数; 類別破壞子=>zh-my:类的析构函数;'),
Item('class instance', 'zh-cn:类的实例; zh-tw:類別的實例;'),
Item('class instance', 'zh-cn:类实例; zh-tw:類別實例;'),
Item('class library', 'zh-cn:类库; zh-tw:類別館;'),
Item('class member', 'zh-cn:类成员; zh-tw:類別成員;'),
Item('class method', 'zh-cn:类方法; zh-tw:類別方法;'),
Item('class of C++', 'zh-cn:C++类; zh-tw:C++類別;'),
Item('class of C++', 'zh-cn:C++的类; zh-tw:C++的類別;'),
Item('class of Java', 'zh-cn:Java类; zh-tw:Java類別;'),
Item('class of Java', 'zh-cn:Java的类; zh-tw:Java的類別;'),
Item('class template', 'zh-cn:类模板; zh-tw:類別模板;'),
Item('class variable', 'zh-cn:类变量; zh-tw:類別變數;'),
Item('class-based', 'zh-cn:基于类; zh-tw:類別為基;'),
Item('class-based programming', 'zh-cn:基于类的编程; zh-tw:類別為基的程式設計;'),
Item('class-orientation', 'zh-cn:面向类; zh-tw:類別導向;'),
Item('classloader', 'zh-cn:类加载器; zh-tw:類別載入器;'),
Item('client', '用戶端=>zh-cn:客户端; 用戶端=>zh-sg:客户端; 用戶端=>zh-my:客户端;'),
Item('clipboard', 'zh:剪貼板; zh-cn:剪贴板; zh-my:剪贴簿; zh-tw:剪貼簿;'),
Item('clock rate', 'zh-cn:时钟频率; zh-tw:時脈頻率; zh-hk:時鐘頻率;'),
Item('clock rate', '時脈速率=>zh-cn:时钟频率; 時脈速率=>zh-sg:时钟频率; 時脈速率=>zh-my:时钟频率;'),
-- 国立编译馆的翻译
Item('clock rate', '時鐘率=>zh-cn:时钟频率; 時鐘率=>zh-sg:时钟频率; 時鐘率=>zh-my:时钟频率;'),
-- 容易過度轉換
Item('clock rate', '時脈=>zh-cn:主频;'),
-- 暂先单向转换,请补充
Item('cloud computing', 'zh:雲計算; zh-cn:云计算; zh-tw:雲端運算;'),
Item('cloud computing storage', 'zh-cn:云存储; zh-sg:云储存; zh-my:云端储存; zh-tw:雲端儲存;'),
Item('cluster', 'zh-cn:集群; zh-tw:叢集;'),
Item('cluster', '群集=>zh-cn:聚类; 群集=>zh-sg:聚类; 群集=>zh-my:聚类;'),
Item('code', '程式碼=>zh-cn:代码; 程式碼=>zh-sg:代码; 程式碼=>zh-my:代码;'),
Item('code generator', 'zh-cn:代码生成器; zh-tw:碼產生器;'),
Item('code page', '代码页=>zh-tw:頁碼; 代码页=>zh-hk:頁碼; 代码页=>zh-mo:頁碼;'),
Item('collaboration', 'zh-cn:协作; zh-tw:協同運作;'),
Item('color monitor', '彩屏=>zh-tw:彩色螢幕; 彩屏=>zh-hk:彩色螢幕; 彩屏=>zh-mo:彩色螢幕;'),
Item('combobox', 'zh-cn:组合框; zh-tw:組合方塊;'),
Item('command line', 'zh-hant:命令列;zh-hans:命令行;'),
-- 有可能過度轉換,編輯時須注意
Item('communication', 'zh:通信;zh-hant:通訊;通訊=>zh-cn:通信;'),
Item('Communicating sequential processes', 'zh-cn:通信顺序进程; zh-tw:交談循序程式;'),
Item('community', '社区=>zh-tw:社群;'),
-- 有可能過度轉換,編輯時須注意
Item('compact disc', 'zh:光盤; zh-cn:光盘; zh-sg:光碟; zh-my:光碟; zh-tw:光碟;'),
Item('compact disc', '光碟片=>zh-cn:光盘;'),
Item('Compact Disc Driver', 'zh-cn:光盘驱动器; zh-sg:光碟机; zh-my:光碟机; zh-tw:光碟機;'),
Item('compatible', 'zh-cn:兼容; zh-tw:相容;'),
Item('compatible', '相兼容=>zh-tw:相容; 相兼容=>zh-hk:相容; 相兼容=>zh-mo:相容;'),
Item('complement', '補數=>zh-cn:补码; 補數=>zh-sg:补码; 補數=>zh-my:补码; 補數=>zh-hk:補碼; 補數=>zh-mo:補碼;'),
Item('complexity class', 'zh-cn:复杂性类; zh-tw:複雜性類別;'),
Item('complexity class', 'zh-cn:复杂度类; zh-tw:複雜度類別;'),
Item('component', '元件=>zh-cn:组件; 元件=>zh-sg:组件; 元件=>zh-my:组件;'),
Item('computer', '计算机=>zh-sg:电脑; 计算机=>zh-my:电脑; 计算机=>zh-tw:電腦; 计算机=>zh-hk:電腦; 计算机=>zh-mo:電腦;'),
Item('computer', '計算機=>zh-sg:电脑; 計算機=>zh-my:电脑;'),
Item('computer', '电子计算机=>zh-sg:电脑; 电子计算机=>zh-my:电脑; 电子计算机=>zh-tw:電腦; 电子计算机=>zh-hk:電腦; 电子计算机=>zh-mo:電腦;'),
Item('computer', '電子計算機=>zh-cn:电子计算机; 電子計算機=>zh-sg:电脑; 電子計算機=>zh-my:电脑;'),
Item('computer architecture', 'zh:計算機體系結構; zh-cn:计算机体系结构; zh-sg:电脑架构; zh-my:电脑架构; zh-tw:電腦架構;'),
Item('computer programming', 'zh:程序設計; zh-cn:程序设计; zh-my:程式设计; zh-tw:程式設計;'),
Item('computer science', 'zh:計算機科學; zh-cn:计算机科学; zh-my:电脑科学; zh-tw:電腦科學;'),
Item('computer terminal', '終端機=>zh-cn:终端; 終端機=>zh-sg:终端; 終端機=>zh-my:终端;'),
Item('computer-generated imagery', 'zh:電腦產生圖像; zh-cn:电脑产生图像; zh-sg:电脑合成影像; zh-my:电脑合成影像; zh-hant:電腦合成影像;'),
Item('concurrency', 'zh-cn:并发; zh-tw:並行;'),
Item('concurrent computing', 'zh-cn:并发计算; zh-tw:並行計算;'),
Item('concurrency-oriented', 'zh-cn:面向并发; zh-tw:平行導向;'),
Item('configure/configuration', 'zh-cn:配置; zh-tw:組態;'),
Item('configuration files', 'zh-cn:配置文件; zh-tw:組態檔;'),
-- Item('connection', 'zh-cn:连接; zh-tw:連線;'), 容易過度轉換
Item('constant', 'zh-cn:常量; zh-tw:常數;'),
Item('constant bitrate', 'zh-cn:固定码率; zh-tw:固定位元速率;'),
Item('constructor', 'zh-cn:构造函数; zh-tw:建構函式;'),
Item('constructor', '建構函數=>zh-cn:构造函数; 建構函數=>zh-tw:建構函式;'),
Item('constructor', '建構子=>zh-cn:构造函数; 建構子=>zh-sg:构造函数; 建構子=>zh-my:构造函数;'),
Item('contact', 'zh-cn:联系; zh-my:联络; zh-tw:聯絡; 連絡=>zh-cn:联系;'),
Item('contact', 'zh:聯繫人; zh-cn:联系人; zh-my:联络人; zh-tw:聯絡人;'),
Item('content-addressable memory', 'zh-cn:内容可寻址存储器; zh-tw:可定址內容記憶體;'),
Item('content-addressable memory', 'zh-cn:结合存储; zh-tw:可定址內容記憶體;'),
Item('context switch', 'zh-cn:上下文切换; zh-tw:上下文交換;'),
Item('Continuity', 'zh-cn:连续互通; zh-tw:接續互通;'),
Item('control', 'zh-cn:控件; zh-tw:控制項;'),
Item('convert', '轉檔=>zh-cn:转换; 轉檔=>zh-sg:转换; 轉檔=>zh-my:转换;'),
Item('copper clad laminate', 'zh-cn:覆铜板; zh-tw:銅箔基板;'),
Item('copyright', 'zh:版权; zh-cn:著作权; zh-tw:著作權; zh-hk:版權; zh-mo:著作權;'),
Item('copyright information', '版权信息=>zh-cn:著作权信息; 版权信息=>zh-sg:著作权信息; 版权信息=>zh-my:著作权信息; 版权信息=>zh-tw:著作權資訊; 版权信息=>zh-mo:著作權資訊;'),
Item('cost-effective', 'zh-cn:性价比; zh-tw:CP值; zh-hk:性價比;'),
Item('cracker', 'zh-cn:溃客; zh-tw:劊客; zh-hk:潰客;'),
Item('crash', 'zh-hk:死機; zh-cn:死机; zh-my:当机; zh-sg:当机; zh-tw:當機;'),
Item('create', 'zh:创建; zh-tw:建立;'),
Item('create', '創建=>zh-tw:建立;'),
Item('create new', 'zh:创建新; zh-tw:新增;'),
Item('create new', '創建新=>zh-tw:新增;'),
Item('CRT', 'zh-cn:显像管; zh-tw:映像管; zh-hk:顯像管;'),
Item('current version', 'zh-cn:当前版本; zh-tw:目前版本;'),
Item('cursor', 'zh-cn:光标; zh-tw:游標;'),
Item('custom', 'zh-cn:自定义; zh-tw:自訂;'),
Item('custom', '自定義=>zh-tw:自訂; 自定義=>zh-hk:自訂; 自定義=>zh-mo:自訂;'),
Item('custom', '自定=>zh-tw:自訂; 自定=>zh-hk:自訂; 自定=>zh-mo:自訂;'),
Item('customization', 'zh-cn:定制; zh-tw:客製化;'),
Item('cut', 'zh-cn:剪切; zh-tw:剪下;'),
Item('cyberbullying', 'zh-cn:网络欺凌; zh-tw:網路霸凌; zh-hk:網上欺凌;'),
Item('Cyber-Physical System', 'zh-cn:信息物理系统; zh-tw:網宇實體系統;'),
{ type = 'text', text = [[
== D ==
]] },
Item('daemon', 'zh-cn:守护进程; zh-tw:守護行程;'),
Item('daisy chaining', 'zh-cn:菊花链接; zh-tw:菊式鏈結;'),
Item('data', '数据=>zh-tw:資料; 数据=>zh-hk:數據;'),
Item('database', 'zh-cn:数据库; zh-tw:資料庫; zh-hk:資料庫;'),
Item('data center', 'zh-cn:数据中心; zh-hk:數據中心; zh-tw:資料中心;'),
Item('data chaining', 'zh-cn:数据链接; zh-tw:資料鏈結;'),
Item('data cleansing', 'zh-cn:数据清洗; zh-tw:資料淨化;'),
Item('data dredging', 'zh-cn:数据捕捞; zh-tw:資料挖掘; zh-hk:數據捕撈;'),
Item('data execution protection', 'zh-cn:数据执行保护; zh-tw:系統記憶體保護; zh-hk:數據執行保護;'),
Item('data frame', 'zh-cn:数据帧; zh-tw:資料訊框; zh-hk:數據幀;'),
Item('data mart', 'zh-cn:数据集市; zh-tw:資料市集; zh-hk:數據市集;'),
Item('data mining', 'zh-cn:数据挖掘; zh-tw:資料探勘; zh-hk:數據探勘;'),
Item('data packet', 'zh:數據包; zh-cn:数据包; zh-tw:封包;'),
Item('data packet', '数据封包=>zh-cn:数据包; 數據封包=>zh-cn:数据包; 資料封包=>zh-cn:数据包;'),
Item('data source', '数据源=>zh-cn:数据源; 数据源=>zh-tw:資料來源; 数据源=>zh-hk:數據源;'),
Item('data type', 'zh-cn:数据类型; zh-hant:資料類型;'),
Item('data warehouse', 'zh-cn:数据仓库; zh-tw:資料倉儲; zh-hk:數據倉庫;'),
Item('datagram', 'zh-cn:数据报文;zh-tw:資料報;'),
Item('deadlock', 'zh-cn:死锁; zh-tw:死結;'),
Item('debug', 'zh-cn:调试; zh-tw:除錯;'),
Item('debug', '除错=>zh-cn:调试; 除错=>zh-sg:调试; 除错=>zh-my:调试;'),
Item('debug', '偵錯=>zh-cn:调试; 偵錯=>zh-sg:调试; 偵錯=>zh-my:调试;'),
Item('debug', '侦错=>zh-cn:调试; 侦错=>zh-sg:调试; 侦错=>zh-my:调试;'),
Item('debug', '調試=>zh-tw:除錯; 調試=>zh-hk:除錯; 調試=>zh-mo:除錯;'),
Item('declaration', '声明语句=>zh-tw:宣告; 声明语句=>zh-hk:宣告; 声明语句=>zh-mo:宣告;'),
Item('decode', '译码=>zh-tw:解碼;译码=>zh-sg:解码;译码=>zh-my:解码;'),
Item('default', 'zh-cn:默认; zh-tw:預設;'),
Item('default', '缺省=>zh-tw:預設; 缺省=>zh-hk:預設; 缺省=>zh-mo:預設;'),
Item('definition', '清晰度=>zh-tw:解析度;'),
Item('defragmentation program', 'zh-cn:磁盘碎片整理程序; zh-tw:磁碟重組工具;'),
Item('defragmentation', 'zh-cn:磁盘碎片整理; zh-tw:磁碟重組;'),
Item('denial-of-service (DoS)', 'zh-cn:拒绝服务; zh-tw:阻斷服務;'),
Item('denormalization', 'zh-cn:反规范化; zh-tw:解除規格化;'),
Item('dependent type', 'zh-cn:依赖类型; zh-tw:依值型別;'),
Item('dependent type', 'zh-cn:依存类型; zh-tw:依存型別;'),
Item('derivation list', 'zh-cn:继承列表; zh-tw:衍化列;'),
Item('derive', 'zh-cn:派生; zh-tw:衍生;'),
Item('derived class', 'zh-cn:派生类; zh-tw:衍生類別;'),
Item('derived type', 'zh-cn:派生类型; zh-tw:衍生類型;'),
Item('desktop', 'zh-cn:桌面型; zh-tw:桌上型;'),
Item('desktop computer', 'zh-cn:台式机; zh-sg:台式电脑; zh-my:台式电脑; zh-tw:桌上型電腦; zh-hk:桌上電腦;'),
Item('desktop computer', '桌上型电脑=>zh-cn:台式机; 桌上型电脑=>zh-sg:台式电脑; 桌上型电脑=>zh-my:台式电脑; 桌上型电脑=>zh-hk:桌上電腦; 桌上型电脑=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上电脑=>zh-cn:台式机; 桌上电脑=>zh-sg:台式电脑; 桌上电脑=>zh-my:台式电脑; 桌上电脑=>zh-tw:桌上型電腦;'),
Item('desktop computer', '台式機=>zh-tw:桌上型電腦; 台式機=>zh-hk:桌上電腦; 台式機=>zh-mo:桌上電腦;'),
Item('desktop computer', '臺式機=>zh-tw:桌上型電腦; 臺式機=>zh-hk:桌上電腦; 臺式機=>zh-mo:桌上電腦;'),
Item('desktop computer', '台式计算机=>zh-tw:桌上型電腦; 台式计算机=>zh-hk:桌上電腦; 台式计算机=>zh-mo:桌上電腦;'),
Item('desktop computer', '台式電腦=>zh-tw:桌上型電腦; 台式電腦=>zh-hk:桌上電腦; 台式電腦=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上型计算机=>zh-hk:桌上電腦; 桌上型计算机=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上型計算機=>zh-hk:桌上電腦; 桌上型計算機=>zh-mo:桌上電腦;'),
Item('desktop computer', '桌上計算機=>zh-tw:桌上型電腦;'),
Item('desktop version', '桌面版=>zh-tw:電腦版; 桌面版=>zh-hk:電腦版; 桌面版=>zh-mo:電腦版;'),
Item('destruct', 'zh-cn:析构; zh-tw:解構;'),
Item('destructor', 'zh-cn:析构函数; zh-tw:解構函式;'),
Item('destructor', '解構函數=>zh-cn:析构函数; 解構函數=>zh-tw:解構函式;'),
Item('destructor', '解構子=>zh-cn:析构函数; 解構子=>zh-sg:析构函数; 解構子=>zh-my:析构函数;'),
Item('device', 'zh:設備; zh-cn:设备; zh-sg:装置; zh-hant:裝置;'),
Item('dialog box', 'zh-cn:对话框; zh-tw:對話方塊;'),
Item('digital', '数码=>zh-tw:數位; 数码=>zh-sg:数码; 数码=>zh-my:数码;'),
Item('digital', '數碼=>zh-cn:数字; 數碼=>zh-sg:数码; 數碼=>zh-my:数码; 數碼=>zh-tw:數位;'),
Item('digital', '数位=>zh-sg:数码; 数位=>zh-my:数码; 数位=>zh-hk:數碼; 数位=>zh-mo:數碼;'),
Item('digital', '數位=>zh-cn:数字; 數位=>zh-sg:数码; 數位=>zh-my:数码; 數位=>zh-hk:數碼; 數位=>zh-mo:數碼;'),
Item('digital', 'zh:數字圖像; zh-cn:数字图像; zh-sg:数码图像; zh-tw:數位影像; zh-hk:數碼圖像;'),
Item('digitalisation', 'zh:數字化; zh-cn:数字化; zh-sg:数码化; zh-my:数码化; zh-tw:數位化; zh-hk:數碼化;'),
Item('digital asset', 'zh:數字資產; zh-cn:数字资产; zh-sg:数码资产; zh-tw:數位資產; zh-hk:數碼資產;'),
Item('digital broadcasting', 'zh:數字廣播; zh-cn:数字广播; zh-sg:数码广播; zh-my:数码广播; zh-tw:數位廣播; zh-hk:數碼廣播;'),
Item('digital camera', 'zh-cn:数字相机; zh-sg:数码相机; zh-my:数码相机; zh-tw:數位相機; zh-hk:數碼相機;'),
Item('digital certificates', 'zh:數字證書; zh-cn:数字证书; zh-sg:数码证书; zh-tw:數位憑證; zh-hk:數碼證書;'),
Item('digital distribution', 'zh:數字發行; zh-cn:数字发行; zh-sg:数码发行; zh-tw:數位發行; zh-hk:數碼發行;'),
Item('digital identity', 'zh-cn:数字身份; zh-sg:数码身份; zh-my:数码身份; zh-tw:數位身分; zh-hk:數碼身份;'),
Item('digital mapping', 'zh-cn:数字测图; zh-my:数码测图; zh-sg:数码制图; zh-tw:數位製圖; zh-hk:數碼製圖;'),
Item('digital media', 'zh:數字媒體; zh-cn:数字媒体; zh-sg:数码媒体; zh-my:数码媒体; zh-tw:數位媒體; zh-hk:數碼媒體;'),
Item('digital mobile', 'zh-cn:数字移动; zh-sg:数码移动; zh-my:数码移动; zh-tw:數位行動; zh-hk:數碼流動;'),
Item('digital mode', 'zh-cn:数字模式; zh-sg:数码模式; zh-my:数码模式; zh-tw:數位模式; zh-hk:數碼模式;'),
Item('digital photo', 'zh-cn:数字照片; zh-sg:数码照片; zh-my:数码相片; zh-tw:數位相片; zh-hk:數碼相片;'),
Item('digital right', 'zh:數字版權; zh-cn:数字版权; zh-my:数码版权; zh-tw:數位版權; zh-hk:數碼版權;'),
Item('digital signature', 'zh:數字簽名; zh-cn:数字签名; zh-sg:数码签名; zh-my:数码签名; zh-tw:數位簽章; zh-hk:數碼簽章;'),
Item('digital television', 'zh:數字電視; zh-cn:数字电视; zh-sg:数码电视; zh-my:数码电视; zh-tw:數位電視; zh-hk:數碼電視;'),
Item('digital terrestrial television', 'zh:數字地面電視;zh-tw:無線數位電視;zh-sg:地面数码电视;zh-my:地面数码电视;zh-hk:地面數碼電視;zh-mo:數碼地面電視;zh-cn:数字地面电视;'), -- 次常用
Item('digital terrestrial television', 'zh:无线数字电视;zh-tw:數位無線電視;zh-sg:数码地面电视;zh-my:数码地面电视;zh-hk:數碼地面電視;zh-mo:地面數字電視;zh-cn:地面数字电视;'), -- 最常用
Item('digital video', 'zh:數字視頻; zh-cn:数字视频; zh-sg:数码视频; zh-my:数码影音; zh-tw:數位影片; zh-hk:數碼影片;'),
Item('digital video', '視像=>zh-tw:視訊; 視像=>zh-cn:视频; 視像=>zh-my:视频; 視像=>zh-sg:视频;'),
Item('digital video', '视像=>zh-tw:視訊; 视像=>zh-cn:视频; 视像=>zh-my:视频; 视像=>zh-sg:视频;'),
Item('digital video', '視頻=>zh-tw:影片; 視頻=>zh-hk:影片; 視頻=>zh-mo:影片;'),
Item('digital video', '视频=>zh-tw:影片; 视频=>zh-hk:影片; 视频=>zh-mo:影片;'),
Item('digital video', '視訊=>zh-hk:視像; 視訊=>zh-mo:視像; 視訊=>zh-cn:视频; 視訊=>zh-my:视频; 視訊=>zh-sg:视频;'),
Item('digital video', '视讯=>zh-mo:視像; 视讯=>zh-hk:視像; 视讯=>zh-cn:视频; 视讯=>zh-my:视频; 视讯=>zh-sg:视频;'),
Item('digital video', 'zh-cn:监控; zh-tw:監視; zh-hk:監視;'),
Item('digital watermarking', 'zh-cn:数字水印; zh-my:数码水印; zh-sg:数码水印; zh-tw:數位浮水印; zh-hk:數碼水印;'),
Item('disk', 'zh:磁盤; zh-cn:磁盘; zh-my:磁碟; zh-tw:磁碟;'),
Item('display device', '显示屏=>zh-tw:顯示器; 显示屏=>zh-hk:顯示器; 显示屏=>zh-mo:顯示器;'),
Item('display memory', 'zh-cn:显示内存; zh-tw:顯示記憶體;'),
Item('distributed', 'zh-cn:分布式; zh-tw:分散式;'),
Item('document', '文档=>zh-tw:文件; 文档=>zh-hk:文件; 文档=>zh-mo:文件;'), --容易过度转换,实际均存在互用的情况
Item('document', '文檔=>zh-tw:文件; 文檔=>zh-hk:文件; 文檔=>zh-mo:文件;'),
Item('document file', 'zh-cn:文档文件; zh-tw:文件檔案;'), --需要确认
Item('document file', '文件檔=>zh-cn:文档文件; 文件檔=>zh-sg:文档文件; 文件檔=>zh-my:文档文件;'),
Item('document-oriented', 'zh-cn:面向文档; zh-tw:文件導向;'),
Item('document object model (DOM)', 'zh-cn:文档对象模型; zh-tw:文件物件模型;'),
Item('do Not Track', 'zh-cn:请勿追踪; zh-tw:停止追蹤;'),
Item('domain-key normal form', 'zh-cn:DK范式; zh-tw:DK規格化;'),
Item('drive', 'zh-cn:磁盘驱动器; zh-tw:磁碟機;'),
Item('drive - A drive', 'zh-cn:A盘; zh-tw:本機磁碟(A); zh-hk:A磁碟機;'),
Item('drive - B drive', 'zh-cn:B盘; zh-tw:本機磁碟(B); zh-hk:B磁碟機;'),
Item('drive - C drive', 'zh-cn:C盘; zh-tw:本機磁碟(C); zh-hk:C磁碟機;'),
Item('drive - D drive', 'zh-cn:D盘; zh-tw:本機磁碟(D); zh-hk:D磁碟機;'),
Item('drive - E drive', 'zh-cn:E盘; zh-tw:本機磁碟(E); zh-hk:E磁碟機;'),
Item('drive - F drive', 'zh-cn:F盘; zh-tw:本機磁碟(F); zh-hk:F磁碟機;'),
Item('drive - G drive', 'zh-cn:G盘; zh-tw:本機磁碟(G); zh-hk:G磁碟機;'),
Item('drive - H drive', 'zh-cn:H盘; zh-tw:本機磁碟(H); zh-hk:H磁碟機;'),
Item('drive - I drive', 'zh-cn:I盘; zh-tw:本機磁碟(I); zh-hk:I磁碟機;'),
Item('drive - J drive', 'zh-cn:J盘; zh-tw:本機磁碟(J); zh-hk:J磁碟機;'),
Item('drive - K drive', 'zh-cn:K盘; zh-tw:本機磁碟(K); zh-hk:K磁碟機;'),
Item('drive - L drive', 'zh-cn:L盘; zh-tw:本機磁碟(L); zh-hk:L磁碟機;'),
Item('drive - M drive', 'zh-cn:M盘; zh-tw:本機磁碟(M); zh-hk:M磁碟機;'),
Item('drive - N drive', 'zh-cn:N盘; zh-tw:本機磁碟(N); zh-hk:N磁碟機;'),
Item('drive - O drive', 'zh-cn:O盘; zh-tw:本機磁碟(O); zh-hk:O磁碟機;'),
Item('drive - P drive', 'zh-cn:P盘; zh-tw:本機磁碟(P); zh-hk:P磁碟機;'),
Item('drive - Q drive', 'zh-cn:Q盘; zh-tw:本機磁碟(Q); zh-hk:Q磁碟機;'),
Item('drive - R drive', 'zh-cn:R盘; zh-tw:本機磁碟(R); zh-hk:R磁碟機;'),
Item('drive - S drive', 'zh-cn:S盘; zh-tw:本機磁碟(S); zh-hk:S磁碟機;'),
Item('drive - T drive', 'zh-cn:T盘; zh-tw:本機磁碟(T); zh-hk:T磁碟機;'),
Item('drive - U drive', 'U磁碟機=>zh-cn:U盘; U磁碟機=>zh-sg:U盘; U磁碟機=>zh-my:U盘; U磁碟機=>zh-tw:USB磁碟機;'),
-- U盘與USB flash drive有衝突
Item('drive - U drive', 'U槽=>zh-cn:U盘; U槽=>zh-sg:U盘; U槽=>zh-my:U盘; U槽=>zh-tw:USB磁碟機; U槽=>zh-hk:U磁碟機; U槽=>zh-mo:U磁碟機;'),
Item('drive - V drive', 'zh-cn:V盘; zh-tw:本機磁碟(V); zh-hk:V磁碟機;'),
Item('drive - W drive', 'zh-cn:W盘; zh-tw:本機磁碟(W); zh-hk:W磁碟機;'),
Item('drive - X drive', 'zh-cn:X盘; zh-tw:本機磁碟(X); zh-hk:X磁碟機;'),
Item('drive - Y drive', 'zh-cn:Y盘; zh-tw:本機磁碟(Y); zh-hk:Y磁碟機;'),
Item('drive - Z drive', 'zh-cn:Z盘; zh-tw:本機磁碟(Z); zh-hk:Z磁碟機;'),
Item('drive - system drive', 'zh-cn:系统盘; zh-tw:系統磁碟; zh-hk:系統磁碟機;'),
Item('drive letter', 'zh-cn:盘符; zh-tw:磁碟機代號;'),
Item('driver', 'zh:驅動程序; zh-cn:驱动程序; zh-my:驱动程式; zh-tw:驅動程式;'),
Item('drop-down menu', 'zh-cn:下拉菜单; zh-tw:下拉式選單;'),
Item('Dual-link', 'zh-cn:双通道; zh-tw:雙連結;'),
Item('duck typing', 'zh-cn:鸭子类型; zh-tw:鴨子型別;'),
Item('dynamic binding', 'zh-cn:动态绑定; zh-tw:動態繫結;'),
Item('dynamic typing', 'zh-cn:动态类型; zh-tw:動態型別;'),
{ type = 'text', text = [[
== E ==
]] },
Item('edit bar', 'zh-cn:编辑栏; zh-tw:編輯列;'),
Item('email', '电子邮件=>zh-sg:电邮; 电子邮件=>zh-my:电邮;'),
Item('email', '電子郵件=>zh-sg:电邮; 電子郵件=>zh-my:电邮;'),
Item('email', '电邮=>zh-tw:電子郵件;'),
Item('email', '電郵=>zh-tw:電子郵件;'),
Item('email', '电子信件=>zh-cn:电子邮件; 电子信件=>zh-sg:电邮; 电子信件=>zh-my:电邮; 电子信件=>zh-tw:電子郵件;'),
Item('email', '電子信件=>zh-cn:电子邮件; 電子信件=>zh-sg:电邮; 電子信件=>zh-my:电邮; 電子信件=>zh-tw:電子郵件;'),
Item('email (mailbox)', 'zh-cn:邮箱; zh-tw:電子信箱; zh-hk:郵箱;'),
Item('email (mailbox)', '电子邮箱=>zh-tw:電子信箱;'),
Item('email (mailbox)', '電子郵箱=>zh-tw:電子信箱;'),
Item('enclosed', '带圈=>zh-tw:圍繞; 带圈=>zh-hk:圍繞; 带圈=>zh-mo:圍繞;'),
Item('enclosed', '帶圈=>zh-tw:圍繞; 帶圈=>zh-hk:圍繞; 帶圈=>zh-mo:圍繞;'),
Item('enclosed character', 'zh-cn:带圈字符; zh-tw:圍繞字元;'),
Item('end user', 'zh-cn:最终用户; zh-tw:終端使用者;'),
Item('end-user license agreements', 'zh-cn:最终用户许可协议; zh-tw:終端使用者授權協定;'),
Item('enter', '回车=>zh-tw:Enter; 回车=>zh-hk:Enter; 回车=>zh-mo:Enter;'),
Item('enter key', 'zh:回車鍵; zh-cn:回车键; zh-sg:确认键; zh-my:确认键; zh-tw:確認鍵;'),
Item('enumeration', 'zh-cn:枚举; zh-tw:列舉;'),
Item('enumerators', 'zh-cn:枚举器; zh-tw:列舉元;'),
Item('enumerators', 'zh-cn:枚举成员; zh-tw:列舉元;'),
Item('escape', 'zh-cn:转义; zh-tw:跳脫;'),
Item('Ethernet', 'zh-cn:以太网; zh-tw:乙太網路;'),
Item('Ethernet', '以太网络 => zh-tw:乙太網路;'),
Item('EULA', 'zh-cn:最终用户许可协议; zh-tw:終端使用者授權合約;'),
Item('Exabyte', 'zh-hans:艾字节; zh-hant:艾位元組;'),
Item('exception handling', 'zh-cn:异常处理; zh-tw:例外處理;'),
Item('exclusive or', 'zh-cn:异或; zh-tw:互斥或; zh-hk:異或;'),
Item('executable file', '可执行文件=>zh-tw:可執行檔;'),
Item('executable file', '執行檔=>zh-cn:可执行文件; 執行檔=>zh-sg:可执行文件; 執行檔=>zh-my:可执行文件;'),
-- Item('exit/quit', 'zh-cn:退出; zh-tw:結束;'), 容易過度轉換
Item('exit/quit application', 'zh-cn:退出程序; zh-tw:結束程式;'),
Item('exit/quit application', 'zh-cn:退出应用程序; zh-tw:結束應用程式; zh-hk:結束應用程序;'),
Item('expand', 'zh-cn:扩展; zh-tw:擴充;'),
Item('export', 'zh-cn:导出; zh-tw:匯出;'),
Item('expression', '運算式=>zh-cn:表达式; 運算式=>zh-sg:表达式; 運算式=>zh-my:表达式;'),
Item('extended block', '扩充区=>zh-cn:扩展区; 扩充区=>zh-sg:扩展区; 扩充区=>zh-my:扩展区;'),
Item('extended block', '擴展區=>zh-tw:擴充區; 擴展區=>zh-hk:擴充區; 擴展區=>zh-mo:擴充區;'),
Item('extended Chinese character', '扩充汉字=>zh-cn:扩展汉字;'),
Item('extended Chinese character', 'zh:擴展漢字; zh-hant:擴充漢字;'),
Item('extended reality', 'zh-cn:扩展现实; zh-tw:延展實境;'),
Item('extensible', 'zh:可擴展; zh-cn:可扩展; zh-tw:可延伸;'),
Item('extensible business reporting language', 'zh-cn:可扩展商业报告语言; zh-tw:可延伸商用報告語言;'),
Item('extensible firmware interface', 'zh-cn:可扩展固件接口; zh-tw:可延伸韌體介面;'),
Item('extensible markup language', 'zh-cn:可扩展置标语言; zh-tw:可延伸標示語言;'),
Item('extension name', 'zh-cn:扩展名; zh-tw:副檔名;'),
Item('extension', '擴充套件=>zh-cn:扩展; 擴充套件=>zh-sg:扩展; 擴充套件=>zh-my:扩展;'),
Item('extension', '擴充功能=>zh-cn:扩展; 擴充功能=>zh-sg:扩展; 擴充功能=>zh-my:扩展;'),
Item('extension A', '扩充A区=>zh-cn:扩展A区; 扩充A区=>zh-sg:扩展A区; 扩充A区=>zh-my:扩展A区;'),
Item('extension A', '擴展A區=>zh-tw:擴充A區; 擴展A區=>zh-hk:擴充A區; 擴展A區=>zh-mo:擴充A區;'),
Item('extension B', '扩充B区=>zh-cn:扩展B区; 扩充B区=>zh-sg:扩展B区; 扩充B区=>zh-my:扩展B区;'),
Item('extension B', '擴展B區=>zh-tw:擴充B區; 擴展B區=>zh-hk:擴充B區; 擴展B區=>zh-mo:擴充B區;'),
Item('extension C', '扩充C区=>zh-cn:扩展C区; 扩充C区=>zh-sg:扩展C区; 扩充C区=>zh-my:扩展C区;'),
Item('extension C', '擴展C區=>zh-tw:擴充C區; 擴展C區=>zh-hk:擴充C區; 擴展C區=>zh-mo:擴充C區;'),
Item('extension D', '扩充D区=>zh-cn:扩展D区; 扩充D区=>zh-sg:扩展D区; 扩充D区=>zh-my:扩展D区;'),
Item('extension D', '擴展D區=>zh-tw:擴充D區; 擴展D區=>zh-hk:擴充D區; 擴展D區=>zh-mo:擴充D區;'),
Item('extension E', '扩充E区=>zh-cn:扩展E区; 扩充E区=>zh-sg:扩展E区; 扩充E区=>zh-my:扩展E区;'),
Item('extension E', '擴展E區=>zh-tw:擴充E區; 擴展E區=>zh-hk:擴充E區; 擴展E區=>zh-mo:擴充E區;'),
Item('extension F', '扩充F区=>zh-cn:扩展F区; 扩充F区=>zh-sg:扩展F区; 扩充F区=>zh-my:扩展F区;'),
Item('extension F', '擴展F區=>zh-tw:擴充F區; 擴展F區=>zh-hk:擴充F區; 擴展F區=>zh-mo:擴充F區;'),
Item('extension G', '扩充G区=>zh-cn:扩展G区; 扩充G区=>zh-sg:扩展G区; 扩充G区=>zh-my:扩展G区;'),
Item('extension G', '擴展G區=>zh-tw:擴充G區; 擴展G區=>zh-hk:擴充G區; 擴展G區=>zh-mo:擴充G區;'),
Item('external hard drive', 'zh-cn:外置硬盘; zh-tw:外接硬碟;'),
Item('external link', '外链=>zh-tw:外部連結; 外链=>zh-hk:外部連結; 外链=>zh-mo:外部連結;'),
Item('external link', '外鏈=>zh-tw:外部連結; 外鏈=>zh-hk:外部連結; 外鏈=>zh-mo:外部連結;'),
Item('enterprise mobility management', 'zh-cn:企业移动管理; zh-tw:企業行動管理;'),
{ type = 'text', text = [[
== F ==
]] },
Item('Facebook', 'zh-cn:脸谱; zh-sg:面簿; zh-my:脸书; zh-tw:臉書;'),
Item('Facebook', '脸谱=>zh-hk:Facebook; 臉譜=>zh-hk:Facebook; 面簿=>zh-hk:Facebook; 脸书=>zh-hk:Facebook; 臉書=>zh-hk:Facebook; 面书=>zh-hk:Facebook; 面書=>zh-hk:Facebook; 脸谱=>zh-mo:Facebook; 臉譜=>zh-mo:Facebook; 面簿=>zh-mo:Facebook; 脸书=>zh-mo:Facebook; 臉書=>zh-mo:Facebook; 面书=>zh-mo:Facebook; 面書=>zh-mo:Facebook;'),
Item('facial recognition', 'zh-cn:人脸识别; zh-tw:臉部辨識; zh-hk:人面辨識;'),
Item('facial recognition', '人臉辨識=>zh-tw:臉部辨識;人臉辨識=>zh-hk:人面辨識;人臉辨識=>zh-mo:人面辨識;'),
Item('fairchild semiconductor', 'zh-cn:仙童半导体;zh-hans:飞兆半导体; zh-tw:快捷半導體;'),
Item('feature phone', 'zh-cn:功能手机; zh-tw:功能型手機; zh-hk:功能電話;'),
Item('feedback', 'zh-cn:反馈; zh-tw:回饋; zh-hk:反饋;'),
Item('fiber distributed data interface', 'zh-cn:光纤分布式数据接口; zh-tw:光纖分散式資料介面; zh-hk:光纖分散式數據介面;'),
Item('field', 'zh-cn:字段; zh-tw:欄位;'),
Item('fifth normal form', 'zh-cn:第五范式; zh-tw:第五規格化;'),
Item('file', 'zh-cn:文件; zh-tw:檔案;'), --容易过度转换,实际均存在互用的情况
Item('dile descriptor', 'zh-cn:文件描述符; zh-hant:檔案描述子;'),
Item('File namespace', 'zh-cn:文件命名空间; zh-tw:檔案命名空間;'),
Item('filename', 'zh-cn:文件名; zh-tw:檔名;'),
Item('filename', 'zh:文件名稱; zh-cn:文件名称; zh-tw:檔案名稱;'),
Item('filename', 'zh-cn:文件名字; zh-tw:檔案名字;'),
Item('filename extension', 'zh-cn:文件扩展名; zh-tw:副檔名;'),
Item('filename extension', 'zh-cn:扩展名; zh-tw:副檔名;'),
Item('film streaming', 'zh-cn:影片流; zh-tw:影片串流;'),
Item('find', 'zh-cn:查找; zh-tw:尋找;'),
Item('firmware', 'zh-cn:固件; zh-tw:韌體;'),
Item('first normal form', 'zh-cn:第一范式; zh-tw:第一規格化;'),
Item('flash memory', 'zh-cn:闪存; zh-tw:快閃記憶體;'),
Item('flight mode', 'zh-cn:飞行模式; zh-tw:飛航模式;'),
Item('floppy disk', 'zh:軟盤; zh-cn:软盘; zh-sg:软碟; zh-tw:軟碟;'),
Item('floppy disk drive', 'zh-cn:软盘驱动器; zh-tw:軟碟機;'),
Item('folder', 'zh:文件夾; zh-cn:文件夹; zh-tw:資料夾;'),
Item('font', 'zh-cn:字体; zh-tw:字型;'),
Item('footer', 'zh-cn:页脚; zh-tw:頁尾;'),
Item('footnote', 'zh-cn:脚注; zh-tw:註腳;'),
Item('footnote', 'zh-cn:尾注; zh-tw:章節附註;'),
Item('foreign key', 'zh-cn:外键; zh-tw:外來鍵;'),
Item('form', 'zh-cn:窗体; zh-tw:表單;'),
Item('forward chaining', 'zh-cn:前向链接; zh-tw:正向鏈結;'),
Item('forward error correction', 'zh-cn:前向纠错; zh-tw:正向錯誤校正;'),
Item('fourth normal form', 'zh-cn:第四范式; zh-tw:第四規格化;'),
Item('frame', 'zh-cn:帧; zh-tw:訊框; zh-hk:幀;'),
Item('frame', '片格=>zh-cn:帧; 片格=>zh-sg:帧; 片格=>zh-my:帧; 片格=>zh-hk:幀; 片格=>zh-mo:幀;'),
Item('frame', '讯框=>zh-cn:帧; 讯框=>zh-sg:帧; 讯框=>zh-my:帧; 讯框=>zh-hk:幀; 讯框=>zh-mo:幀;'),
Item('frame', '影格=>zh-cn:帧; 影格=>zh-sg:帧; 影格=>zh-my:帧; 影格=>zh-hk:幀; 影格=>zh-mo:幀;'),
Item('frame', '畫格=>zh-cn:帧; 畫格=>zh-sg:帧; 畫格=>zh-my:帧; 畫格=>zh-hk:幀; 畫格=>zh-mo:幀;'),
Item('frame rate', 'zh-cn:帧率; zh-tw:影格率; zh-hk:幀率;'),
Item('frame rate', '影格速率=>zh-cn:帧率; 影格速率=>zh-sg:帧率; 影格速率=>zh-my:帧率; 影格速率=>zh-hk:幀率; 影格速率=>zh-mo:幀率;'),
Item('frame pointer', 'zh-cn:帧指针; zh-tw:影格指標; zh-hk:框指標;'),
Item('frame synchronization', 'zh-cn:帧同步; zh-tw:影格同步化; zh-hk:框同步化;'),
Item('forum', 'zh-cn:论坛; zh-tw:論壇; zh-hk:討論區;'),
Item('full screen', 'zh-cn:全屏; zh-tw:全螢幕; zh-hk:全螢幕;'),
Item('full screen', '全面屏=>zh-tw:全螢幕; 全面屏=>zh-hk:全螢幕; 全面屏=>zh-mo:全螢幕;'),
Item('full-size smartphone', 'zh-cn:全面屏手机; zh-tw:全螢幕手機; zh-hk:全螢幕手機;'),
Item('fullwidth', 'zh-cn:全角; zh-tw:全形;'),
Item('function', 'zh-cn:函数; zh-tw:函式; zh-hk:函數;'),
-- terms.naer.edu.tw
Item('functional programming', 'zh-cn:函数式编程; zh-tw:函數式程式設計;'),
Item('functional programming', '函式語言程式設計=>zh-cn:函数式编程; 函式語言程式設計=>zh-tw:函數式程式設計;'),
Item('functional programming language', 'zh-cn:函数编程语言; zh-tw:函數式程式語言;'),
Item('functional programming language', '函數式程式語言=>zh-cn:函数编程语言; 函數式程式語言=>zh-sg:函数编程语言; 函數式程式語言=>zh-my:函数编程语言;'),
Item('functional programming language', '函數程式語言=>zh-cn:函数编程语言; 函數程式語言=>zh-sg:函数编程语言; 函數程式語言=>zh-my:函数编程语言;'),
Item('functional programming language', '函式程式語言=>zh-cn:函数编程语言; 函式程式語言=>zh-sg:函数编程语言; 函式程式語言=>zh-my:函数编程语言; 函式程式語言=>zh-tw:函數式程式語言;'),
Item('full high definition (full HD)', '全高清=>zh-tw:超高畫質;'),
{ type = 'text', text = [[
== G ==
]] },
-- 参考文献:刘青,温昌斌,海峡两岸科技名词差异问题分析与试解,中国科技术语,(3), 2008, 65-69
Item('garbage', '无用信息=>zh-tw:多餘的資料; 无用信息=>zh-hk:多餘的資料; 无用信息=>zh-mo:多餘的資料;'),
Item('gateway', 'zh-cn:网关; zh-tw:閘道器;'),
Item('gateway', '閘道=>zh-cn:网关; 閘道=>zh-sg:网关; 閘道=>zh-my:网关;'),
Item('Gateway, Inc.', 'zh-cn:捷威; zh-tw:桀威;'),
Item('get', 'zh-cn:获取; zh-tw:取得;'),
Item('gigabit ethernet', 'zh-cn:吉比特以太网; zh-tw:十億位元乙太網路;'),
Item('Gigabyte', '吉咖字节=>zh-hant:吉位元組; 京字节=>zh-hant:吉位元組; 吉字节=>zh-hant:吉位元組; '),
Item('Gigabyte', '吉位元組=>zh-hans:吉字节; 十億位元組=>zh-hans:吉字节; '),
Item('global', 'zh-cn:全局; zh-tw:全域;'),
Item('Global System for Mobile Communications Association', 'zh-cn:全球移动通信系统协会; zh-tw:全球行動通訊系統協會; zh-hk:全球流動通訊系統協會;'),
--Item('Google', 'zh:谷歌; zh-hant:Google; 谷歌=>zh-sg:Google; 谷歌=>zh-my:Google;'),
Item('Google Cloud Messaging', 'zh-cn:Google云消息传递; zh-tw:Google雲端通訊;'),
Item('Google Cloud Messaging', 'Google云端推送=>zh-tw:Google雲端通訊; Google云端推送=>zh-hk:Google雲端通訊; Google云端推送=>zh-mo:Google雲端通訊;'),
Item('Google Chrome Frame', 'zh-cn:谷歌浏览器内嵌框架; zh-tw:Google Chrome內嵌瀏覽框;'),
Item('Google Docs', 'zh-cn:Google文档; zh-tw:Google文件;'),
Item('Google Docs', 'zh-cn:Google 文档; zh-tw:Google 文件;'),
Item('Google Toolbar', 'zh-cn:Google工具条; zh-tw:Google工具列;'),
Item('Google Toolbar', 'zh-cn:Google 工具条; zh-tw:Google 工具列;'),
Item('Google Video', 'zh-cn:Google视频; zh-tw:Google影片;'),
Item('Google Video', 'zh-cn:Google 视频; zh-tw:Google 影片;'),
Item('graphics', 'zh-cn:图形学; zh-tw:圖學;'),
Item('graphics', '图学=>zh-cn:图形学; 图学=>zh-sg:图形学; 图学=>zh-my:图形学;'),
Item('graphics', '圖形學=>zh-tw:圖學; 圖形學=>zh-hk:圖學; 圖形學=>zh-mo:圖學;'),
Item('graphics processing unit', 'zh-cn:图形处理器; zh-tw:圖形處理器'),
Item('graphing calculator', 'zh-cn:图形计算器; zh-tw:繪圖計算機;'),
Item('greedy algorithm', 'zh-cn:贪心算法; zh-tw:貪婪演算法;'),
Item('Green Screen', 'zh-hant:綠屏; zh-cn:绿屏; zh-tw:綠白畫面; zh-hk:綠畫面;'),
Item('Green Screen of Death', 'zh-hant:綠屏死機; zh-cn:绿屏死机; zh-tw:綠白當機; zh-hk:綠畫面死機;'),
Item('greedy algorithm', '贪婪算法=>zh-cn:贪心算法; 贪婪算法=>zh-sg:贪心算法; 贪婪算法=>zh-my:贪心算法;'),
Item('greedy algorithm', '貪心算法=>zh-tw:貪婪演算法; 貪心算法=>zh-hk:貪婪演算法; 貪心算法=>zh-mo:貪婪演算法;'),
Item('greedy algorithm', '貪心演算法=>zh-tw:貪婪演算法; 貪心演算法=>zh-hk:貪婪演算法; 貪心演算法=>zh-mo:貪婪演算法;'),
Item('greedy algorithm', 'zh:貪心法; zh-cn:贪心法; zh-tw:貪婪法;'),
Item('gridlines', 'zh-cn:网格线; zh-tw:格線;'),
Item('group', 'zh-cn:组群; zh-tw:群組;'),
Item('group notice', 'zh-cn:组提示; zh-tw:群組提示;'),
Item('GSM mobile', 'zh-cn:GSM移动; zh-tw:GSM行動; zh-hk:GSM流動;'),
Item('GUI', 'zh-cn:图形用户界面; zh-tw:圖形化使用者介面;'),
Item('GUID Partition Table', 'zh-cn:全局唯一标识分区表; zh-tw:GUID磁碟分割表;'),
{ type = 'text', text = [[
== H ==
]] },
Item('hacker', 'zh-cn:黑客; zh-my:骇客; zh-tw:駭客; zh-hk:黑客;'),
Item('halfwidth', 'zh-cn:半角; zh-tw:半形;'),
Item('handler', 'zh-cn:处理函数; zh-tw:處理常式;'),
Item('handle', 'zh-cn:句柄; zh-tw:控制代碼;'),
Item('hard disk', 'zh:硬盤; zh-cn:硬盘; zh-tw:硬碟;'),
Item('hard disk drive (HDD)', 'zh-cn:硬盘驱动器; zh-tw:硬碟機;'),
Item('hard-coded', 'zh-cn:硬编码; zh-tw:寫死;'),
Item('hardware', 'zh-cn:硬件; zh-tw:硬體; zh-hk:硬件;'),
Item('hash', '哈希=>zh-tw:雜湊; 哈希=>zh-hk:雜湊; 哈希=>zh-mo:雜湊;'),
Item('hash', 'zh-cn:散列; zh-tw:雜湊;'),
Item('HDMI', 'zh-cn:高清多媒体接口; zh-tw:高畫質多媒體介面; zh-hk:高清多媒體介面;'),
Item('head crash', 'zh-cn:磁头划碰; zh-tw:磁頭損壞;'),
Item('header', 'zh-cn:标头; zh-tw:檔頭;'),
Item('header', 'zh-cn:页眉; zh-tw:頁首;'),
Item('header file', 'zh-cn:头文件; zh-tw:標頭檔;'),
Item('header file', '標頭檔案=>zh-cn:头文件; 標頭檔案=>zh-sg:头文件; 標頭檔案=>zh-my:头文件;'),
Item('header file', '表頭檔=>zh-cn:头文件; 表頭檔=>zh-sg:头文件; 表頭檔=>zh-my:头文件;'),
Item('header file', '表頭檔案=>zh-cn:头文件; 表頭檔案=>zh-sg:头文件; 表頭檔案=>zh-my:头文件;'),
Item('heapsort', 'zh-cn:堆排序; zh-tw:堆積排序;'),
Item('hearts', 'zh-cn:红心大战; zh-tw:傷心小棧;'),
Item('Help and Support', 'zh-cn:帮助与支持; zh-tw:說明與支援;'),
Item('help document', 'zh-cn:帮助文档; zh-tw:說明文件;'),
Item('Hierarchical View', 'zh-cn:分层视图; zh-tw:多層次樹狀介面;'),
Item('Hierarchical View', 'zh-cn:分层树形视图; zh-tw:多層次樹狀介面;'),
Item('hierarchy', 'zh-cn:层次结构; zh-tw:階層;'),
Item('high bandwidth memory','zh-cn:高带宽内存; zh-tw:高頻寬記憶體;'),
Item('high definition (HD)', 'zh-cn:高清; zh-tw:高畫質; zh-hk:高清;'),
Item('high definition (HD)', 'zh-cn:高清晰; zh-tw:高解析; zh-hk:高清晰;'),
Item('high fidelity (Hi-Fi)', '高保真=>zh-hk:高傳真; 高保真=>zh-mo:高傳真;'),
Item('high fidelity (Hi-Fi)', '高傳真=>zh-cn:高保真; 高傳真=>zh-sg:高保真; 高傳真=>zh-my:高保真;'),
Item('high-resolution audio', 'zh-cn:高清音频; zh-tw:高音質音訊; zh-hk:高清音頻;'),
Item('high-resolution sound quality', 'zh-cn:高清音质; zh-tw:高音質; zh-hk:高清音質;'),
Item('high-level language', 'zh-cn:高级语言; zh-tw:高階語言;'),
Item('high-level language', '高阶语言=>zh-cn:高级语言; 高阶语言=>zh-sg:高级语言; 高阶语言=>zh-my:高级语言;'),
Item('high-level language', '高级語言=>zh-tw:高階語言; 高级語言=>zh-hk:高階語言; 高级語言=>zh-mo:高階語言;'),
Item('high-level language', '高級語言=>zh-tw:高階語言; 高級語言=>zh-hk:高階語言; 高級語言=>zh-mo:高階語言;'),
Item('high-level programming language', 'zh-cn:高级编程语言; zh-tw:高階程式語言;'),
Item('high-level programming language', '高级编程語言=>zh-tw:高階程式語言; 高级编程語言=>zh-hk:高階程式語言; 高级编程語言=>zh-mo:高階程式語言;'),
Item('high-level programming language', '高级编程語言=>zh-tw:高階程式語言; 高级编程語言=>zh-hk:高階程式語言; 高级编程語言=>zh-mo:高階程式語言;'),
Item('highlight', '高亮=>zh-tw:突顯; 高亮=>zh-hk:突顯; 高亮=>zh-mo:突顯;'),
Item('highlight', '高亮显示=>zh-tw:突出顯示; 高亮显示=>zh-hk:突出顯示; 高亮显示=>zh-mo:突出顯示;'),
Item('highlight', '高亮顯示=>zh-tw:突出顯示; 高亮顯示=>zh-hk:突出顯示; 高亮顯示=>zh-mo:突出顯示;'),
Item('holographic', 'zh-cn:全息; zh-tw:全像;'),
Item('home', '住家=>zh-cn:家庭; 住家=>zh-sg:家庭; 住家=>zh-my:家庭;'),
Item('home address', '住家地址=>zh-cn:家庭地址; 住家地址=>zh-sg:家庭地址; 住家地址=>zh-my:家庭地址;'),
Item(nil, 'zh-cn:主页; zh-tw:首頁;'),
Item('hosting', 'zh:託管; zh-cn:托管; zh-tw:代管; zh-hk:寄存; zh-mo:寄存;'),
Item('hook', 'zh-cn:钩子; zh-tw:勾點;'),
Item('HyperText Markup Language', 'zh-cn:超文本标记语言; zh-tw:超文件標示語言;'),
Item('HyperText Markup Language', 'zh-cn:超文本置标语言; zh-tw:超文件標示語言;'),
{ type = 'text', text = [[
== I ==
]] },
Item('icon', 'zh:圖標; zh-cn:图标; zh-tw:圖示;'),
Item('Integrated Development Environment (IDE)', 'zh-cn:集成开发环境; zh-tw:整合式開發環境;'),
Item('Integrated Device Electronics (IDE)', 'zh-cn:集成设备电路; zh-tw:整合裝置電路;'),
Item('ID', 'zh-cn:身份; zh-tw:身分; zh-hk:身份;'),
Item('identifier', 'zh:標識符; zh-cn:标识符; zh-tw:識別碼;'),
Item('if and only if', 'zh:當且僅當; zh-cn:当且仅当; zh-tw:若且唯若;'),
-- 有可能過度轉換,編輯時須注意
Item('image', '映象=>zh-cn:镜像; 映象=>zh-sg:镜像; 映象=>zh-my:镜像;'),
Item('image file', 'zh-cn:图像文件; zh-tw:圖檔;'),
Item('image macro', 'zh-cn:表情包; zh-my:梗图; zh-tw:哏圖;'),
Item('image macro', '表情图=>zh-cn:表情包; 表情圖=>zh-cn:表情包; 表情图=>zh-tw:哏圖; 表情圖=>zh-tw:哏圖;'),
Item('imperative programming', 'zh-cn:命令式编程; zh-tw:指令式程式設計;'),
Item('implement', '實作=>zh-cn:实现; 實作=>zh-sg:实现; 實作=>zh-my:实现;'),
Item('import', 'zh-cn:导入; zh-tw:匯入;'),
Item('import', '汇入=>zh-cn:导入; 汇入=>zh-sg:导入; 汇入=>zh-my:导入;'),
Item('import', '導入=>zh-tw:匯入; 導入=>zh-hk:匯入; 導入=>zh-mo:匯入;'),
Item('Incognito mode', 'zh-cn:隐身模式; zh-my:无痕模式; zh-tw:無痕模式;'),
Item('indent', 'zh-cn:缩进; zh-tw:縮排;'),
Item('info (information)', 'zh-cn:信息; zh-my:资讯; zh-hant:資訊;'),
Item('info (information)', '资讯=>zh-sg:资讯; 資訊=>zh-sg:资讯; 资讯=>zh-cn:资讯;'),
Item('information age', 'zh-cn:信息时代; zh-hans:资讯时代; zh-tw:資訊時代; zh-hk:資訊年代;'),
Item('Information and Communication Technology', 'zh:信息与通信技术;zh-cn:信息和通信技术;zh-tw:資訊及通訊科技;'),
Item('Information Engagement', 'zh-cn:信息接触; zh-my:资讯接触; zh-tw:資訊參與;'),
Item('Information industry', 'zh-cn:信息产业; zh-tw:資訊工業;'),
Item('Information Management', 'zh-cn:信息管理; zh-hans:资讯管理; zh-tw:資訊管理;'),
Item('Information overload', 'zh-cn:信息过载; zh-hk:資訊超載; zh-tw:資訊超載;'),
Item('Information Science', 'zh:信息科學; zh-cn:信息科学; zh-my:资讯科学; zh-tw:資訊學; zh-hk:資訊科學;'),
Item('Information Science', 'zh:信息學; zh-cn:信息学; zh-my:资讯学; zh-tw:資訊學; zh-hk:資訊科學;'),
Item('information security', 'zh-cn:信息安全; zh-my:资讯安全; zh-tw:資訊安全; zh-hk:資訊保安;'),
Item('information security', '資安=>zh-cn:信息安全;'),
Item('Information Technology', 'zh:信息技術; zh-cn:信息技术; zh-sg:资讯科技; zh-my:资讯科技; zh-tw:資訊科技;'),
Item('injection', '隱碼=>zh-cn:注入; 隱碼=>zh-sg:注入; 隱碼=>zh-my:注入;'),
Item('injection', '資料隱碼=>zh-cn:注入; 資料隱碼=>zh-sg:注入; 資料隱碼=>zh-my:注入;'),
Item('inline', 'zh-cn:内联; zh-tw:行內;'),
Item('Intranet', 'zh-cn:内联网; zh-tw:內部網路;'),
Item('installation package', 'zh-cn:安装包; zh-tw:安裝套件;'),
Item('instance method', '實體方法=>zh-cn:实例方法; 實體方法=>zh-sg:实例方法; 實體方法=>zh-my:实例方法;'),
Item('integrate', 'zh-cn:集成; zh-tw:整合;'),
Item('integrated circuit', 'zh-cn:集成电路; zh-tw:積體電路; zh-hk:集成電路;'),
Item('intellectual property', 'zh-cn:知识产权; zh-tw:智慧財產權; zh-hk:知識產權;'),
Item('intellectualize', 'zh-cn:智能化; zh-tw:智慧化; zh-hk:智能化;'),
Item('intelligence', '智能型=>zh-sg:智慧型; 智能型=>zh-my:智慧型; 智能型=>zh-tw:智慧型;'),
Item('interacts', 'zh-cn:交互; zh-tw:互動;'),
Item('interactive entertainment', '互動娛樂=>zh-cn:互动娱乐; 互動娛樂=>zh-sg:互动娱乐; 互動娛樂=>zh-my:互动娱乐;'),
Item('interface', 'zh-cn:接口; zh-tw:介面;'),
Item('interface (frontstage)', '界面=>zh-tw:介面; 界面=>zh-hk:介面; 界面=>zh-mo:介面;'),
Item('internal link', '内链=>zh-tw:內部連結; 内链=>zh-hk:內部連結; 内链=>zh-mo:內部連結;'),
Item('internal link', '內鏈=>zh-tw:內部連結; 內鏈=>zh-hk:內部連結; 內鏈=>zh-mo:內部連結;'),
Item('Internet', 'zh-cn:互联网; zh-tw:網際網路; zh-hk:互聯網;'),
Item('Internet', '英特网=>zh-tw:網際網路; 英特网=>zh-hk:互聯網; 英特网=>zh-mo:互聯網;'),
Item('Internet', '因特网=>zh-tw:網際網路; 因特网=>zh-hk:互聯網; 因特网=>zh-mo:互聯網;'),
Item('Internet', '国际互联网=>zh-tw:網際網路; 国际互联网=>zh-hk:互聯網; 国际互联网=>zh-mo:互聯網;'),
Item('Internet bar', 'zh-cn:网吧; zh-tw:網咖; zh-hk:網吧;'),
Item('Internet culture', '网络文化=>zh-tw:網路文化;'),
Item('Internet forum', '網上論壇=>zh-tw:網路論壇;'),
Item('Internet forum', '網上討論區=>zh-tw:網路論壇;'),
Item('Internet Content Provider (ICP)', 'zh-cn:互联网内容提供商; zh-sg:互联网内容供应商; zh-my:互联网内容供应商; zh-tw:線上內容提供者; zh-hk:互聯網內容供應商;'),
Item('Internet Service Provider (ISP)', 'zh-cn:互联网服务提供商; zh-sg:互联网服务供应商; zh-my:互联网服务供应商; zh-tw:網際網路服務提供者; zh-hk:互聯網服務供應商;'),
Item('interpreter', 'zh-cn:解释器; zh-tw:直譯器;'),
Item('Interpreted language', 'zh-cn:解释型语言; zh-tw:直譯語言;'),
Item('Intranet', 'zh-cn:内部网络; zh-tw:內部網路; zh-hk:內聯網;'),
Item('Intranet', 'zh-cn:内部网; zh-tw:內部網路; zh-hk:內聯網;'),
Item('Internet Key Exchange', 'zh-cn:因特网密钥交换; zh-tw:網際網路金鑰交換; zh-hk:互聯網金鑰交換;'),
Item('Inter-Process Communication', 'zh-cn:进程间通信; zh-tw:行程間通訊; zh-hk:行程間通訊;'),
Item('Inter-Process', 'zh-cn:进程间; zh-tw:行程間; zh-hk:行程間;'),
-- 與call的轉換有衝突
Item('invoke', '叫用=>zh-cn:调用; 叫用=>zh-sg:调用; 叫用=>zh-my:调用;'),
{ type = 'text', text = [[
== J ==
]] },
Item('judge', 'zh-cn:评测系统; zh-tw:解題系統;'),
{ type = 'text', text = [[
== K ==
]] },
Item('kernel', '内核=>zh-tw:核心;'),
Item('kernel', '內核=>zh-tw:核心;'),
Item('key', 'zh:密鑰; zh-cn:密钥; zh-tw:金鑰;'),
Item('keyboard layout', 'zh-cn:键盘布局; zh-tw:鍵盤配置;'),
Item('keygen', 'zh-cn:注册机; zh-tw:序號產生器;'),
{ type = 'text', text = [[
== L ==
]] },
Item('landscape', 'zh-cn:横屏幕; zh-tw:橫螢幕; zh-hk:橫螢幕;'),
Item('landscape', '橫屏=>zh-tw:橫螢幕; 橫屏=>zh-hk:橫螢幕; 橫屏=>zh-mo:橫螢幕;'),
Item('Language-Oriented Programming', 'zh-cn:面向语言的程序设计; zh-tw:語言導向程式設計;'),
Item('language package', 'zh-cn:语言包; zh-tw:語言套件;'),
Item('laptop/notebook computer', 'zh-cn:笔记本电脑; zh-tw:筆記型電腦; zh-hk:手提電腦; zh-sg:手提电脑; zh-my:手提电脑;'),
Item('laptop/notebook computer', '笔记型电脑=>zh-cn:笔记本电脑; 笔记型电脑=>zh-sg:手提电脑; 笔记型电脑=>zh-my:手提电脑; 笔记型电脑=>zh-hk:手提電腦; 笔记型电脑=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '筆記本電腦=>zh-tw:筆記型電腦; 筆記本電腦=>zh-hk:手提電腦; 筆記本電腦=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '笔电=>zh-sg:手提电脑; 笔电=>zh-my:手提电脑; 笔电=>zh-hk:手提電腦; 笔电=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '筆電=>zh-sg:手提电脑; 筆電=>zh-my:手提电脑; 筆電=>zh-hk:手提電腦; 筆電=>zh-mo:手提電腦;'),
Item('laptop/notebook computer', '膝上型电脑=>zh-cn:笔记本电脑; 膝上型电脑=>zh-sg:手提电脑; 膝上型电脑=>zh-my:手提电脑; 膝上型电脑=>zh-tw:筆記型電腦;'),
Item('laptop/notebook computer', '膝上型電腦=>zh-cn:笔记本电脑; 膝上型電腦=>zh-sg:手提电脑; 膝上型電腦=>zh-my:手提电脑; 膝上型電腦=>zh-tw:筆記型電腦;'),
Item('laser', 'zh-cn:激光; zh-sg:镭射; zh-my:雷射; zh-tw:雷射; zh-hk:激光;'),
Item('LaserDisc', 'zh-cn:激光视盘; zh-sg:镭射碟; zh-my:镭射影碟; zh-tw:雷射影碟; zh-hk:鐳射影碟;'),
Item('launch bar', 'zh-cn:启动栏; zh-tw:啟動列;'),
Item('library', '函式庫=>zh-cn:库; 函式庫=>zh-sg:库; 函式庫=>zh-my:库; 函式庫=>zh-tw:函式庫; 函式庫=>zh-hk:函式庫; 函式庫=>zh-mo:函式庫'),
Item('like', 'zh-cn:点赞; zh-tw:按讚; zh-hk:讚好;'),
-- 「链接」有chaining或link的意思,而chaining和link都可被譯為「鏈結」
Item('link', 'zh-cn:链接; zh-tw:連結;'),
Item('link', '鏈結=>zh-cn:链接; 鏈結=>zh-sg:链接; 鏈結=>zh-my:链接;'),
Item('link', '连结=>zh-cn:链接; 连结=>zh-sg:链接; 连结=>zh-my:链接;'),
Item('link', '鏈接=>zh-tw:鏈結; 鏈接=>zh-hk:連結; 鏈接=>zh-mo:連結;'),
Item('linked list', 'zh-cn:链表; zh-tw:鏈結串列;'),
Item('linked list', '鏈表=>zh-tw:鏈結串列; 鏈表=>zh-hk:連結串列; 鏈表=>zh-mo:連結串列;'),
Item('livelock', 'zh-cn:活锁; zh-tw:活結;'),
Item('load', 'zh-cn:加载; zh-tw:載入;'),
Item('load', '载入=>zh-cn:加载; 载入=>zh-sg:加载; 载入=>zh-my:加载;'),
Item('load', '加載=>zh-tw:載入; 加載=>zh-hk:載入; 加載=>zh-mo:載入;'),
Item('Local Area Network', 'zh-cn:局域网; zh-tw:區域網路; zh-hk:區域網絡;'),
Item('localization', 'zh-cn:本地化; zh-tw:在地化; zh-hk:本地化;'),
Item('log', 'zh-cn:日志; zh-tw:紀錄檔;'),
Item('log in', 'zh-hans:登录; zh-hant:登入;'),
Item('log out', '登出=>zh-cn:退出; 登出=>zh-my:退出; 登出=>zh-sg:退出;'),
Item('logic device', 'zh-cn:逻辑器件; zh-tw:邏輯裝置;'),
Item('logic gate', 'zh-cn:逻辑门; zh-tw:邏輯閘; zh-hk:邏輯門;'),
Item('loop', 'zh-cn:循环; zh-tw:迴圈;'),
Item('lossless', 'zh-cn:无损; zh-tw:無失真;'),
Item('lossless compression', 'zh-cn:无损压缩; zh-tw:無失真壓縮; zh-hk:無損壓縮;'),
Item('lossy compression', 'zh-cn:有损压缩; zh-tw:失真壓縮;'),
Item('lost', 'zh-cn:丢失; zh-tw:遺失;'),
Item('low definition', 'zh-cn:低清; zh-tw:低畫質; zh-hk:低清;'),
Item('low level', 'zh-cn:低级; zh-tw:低階;'),
Item('low level', 'zh-cn:低端; zh-tw:低階;'),
Item('low-level language', 'zh-cn:低级语言; zh-tw:低階語言;'),
Item('low-level language', '低阶语言=>zh-cn:低级语言; 低阶语言=>zh-sg:低级语言; 低阶语言=>zh-my:低级语言;'),
Item('low-level language', '低级語言=>zh-tw:低階語言; 低级語言=>zh-hk:低階語言; 低级語言=>zh-mo:低階語言;'),
Item('low-level language', '低級語言=>zh-tw:低階語言; 低級語言=>zh-hk:低階語言; 低級語言=>zh-mo:低階語言;'),
Item('low-level programming language', 'zh-cn:低级编程语言; zh-tw:低階程式語言;'),
Item('low-level programming language', '低级编程語言=>zh-tw:低階程式語言; 低级编程語言=>zh-hk:低階程式語言; 低级编程語言=>zh-mo:低階程式語言;'),
{ type = 'text', text = [[
== M ==
]] },
Item('machine code', 'zh-cn:机器代码; zh-tw:機器碼; zh-hk:機械碼;'),
Item('machine code', '機器代碼=>zh-tw:機器碼; 機器代碼=>zh-hk:機械碼; 機器代碼=>zh-mo:機械碼;'),
Item('machine code', '机器码=>zh-tw:機器碼; 机器码=>zh-hk:機械碼; 机器码=>zh-mo:機械碼;'),
Item('mailing list', 'zh-cn:邮件列表; zh-tw:郵寄清單;'),
Item('mainstream media', 'zh-cn:主流媒体; zh-tw:主流媒體;'),
Item('managed code', 'zh-cn:托管代码; zh-tw:受控代碼;'),
Item('managed code', '受控代码=>zh-cn:托管代码; 受控代码=>zh-sg:托管代码; 受控代码=>zh-my:托管代码;'),
Item('managed code', '託管代碼=>zh-tw:受控代碼; 託管代碼=>zh-hk:受控代碼; 託管代碼=>zh-mo:受控代碼;'),
-- 單向轉換以避免過度轉換
Item('macro', '巨集=>zh-cn:宏; 巨集=>zh-sg:宏; 巨集=>zh-my:宏;'),
Item('macro virus', 'zh-cn:宏病毒; zh-tw:巨集病毒;'),
Item('macroblock', 'zh-cn:宏块; zh-tw:大區塊;'),
Item('macroblock', '大区块=>zh-cn:宏块; 大区块=>zh-sg:宏块; 大区块=>zh-my:宏块;'),
Item('macroblock', '宏塊=>zh-tw:大區塊; 宏塊=>zh-hk:大區塊; 宏塊=>zh-mo:大區塊;'),
Item('macroblock', '宏區塊=>zh-tw:大區塊; 宏區塊=>zh-hk:大區塊; 宏區塊=>zh-mo:大區塊;'),
Item('main memory', 'zh-hans:主存储器; zh-hant:主記憶體;'),
Item('main memory', '主存=>zh-tw:主記憶體; 主存=>zh-hk:主記憶體; 主存=>zh-mo:主記憶體;'),
Item('main memory', '内存储器=>zh-tw:主記憶體; 内存储器=>zh-hk:主記憶體; 内存储器=>zh-mo:主記憶體;'),
Item('main memory', '内存=>zh-tw:主記憶體; 内存=>zh-hk:主記憶體; 内存=>zh-mo:主記憶體;'),
Item('main memory', '內存=>zh-tw:主記憶體; 內存=>zh-hk:主記憶體; 內存=>zh-mo:主記憶體;'),
Item('mainframe', 'zh-cn:大型机; zh-tw:大型電腦;'),
Item('mapping', 'zh-cn:映射; zh-tw:對映;'),
Item('marketing', 'zh-cn:营销; zh-tw:行銷;'),
Item('Markup Language', 'zh-cn:置标语言; zh-tw:標示語言;'),
Item('Markup Language', 'zh-cn:标记语言; zh-tw:標示語言;'),
Item('Markup Language', 'zh-cn:标记语言; zh-tw:標記式語言;'),
Item('mask', '掩码=>zh-tw:遮罩; 掩码=>zh-hk:遮罩; 掩码=>zh-mo:遮罩;'),
Item('Master Boot Record', 'zh-cn:主引导记录; zh-tw:主開機紀錄;'),
-- Item('match', '匹配=>zh-tw:符合; 匹配=>zh-hk:符合; 匹配=>zh-mo:符合;'), 容易過度轉換,部分須轉換為「相符」
Item('media streamming', 'zh-cn:流媒体; zh-tw:串流媒體;'),
Item('medium', 'zh-cn:介质; zh-tw:媒介;'),
Item('medium', '媒质=>zh-tw:媒介; 媒质=>zh-hk:媒介; 媒质=>zh-mo:媒介;'),
Item('medium dependent interface', 'zh-cn:介质相关接口; zh-tw:媒體相依介面;'),
Item('megabyte', 'zh-hans:兆字节; zh-hant:百萬位元組;'),
Item('memory', 'zh-cn:存储器; zh-tw:記憶體;'),
Item('memory', '電腦記憶體=>zh-cn:存储器;'),
Item('memory card', 'zh-cn:存储卡; zh-tw:記憶卡;'),
Item('memory chip', 'zh-cn:存储芯片; zh-tw:記憶晶片;'),
Item('memory leak', 'zh-cn:内存泄漏; zh-tw:記憶體漏失;'),
Item('memory leak', 'zh-cn:内存泄漏; zh-tw:記憶體流失;'),
Item('menu', 'zh-cn:菜单; zh-tw:選單;'),
Item('merge', '归并=>zh-tw:合併; 归并=>zh-hk:合併; 归并=>zh-mo:合併;'),
Item('message', 'zh-cn:消息; zh-tw:訊息;'),
Item('message authentication code', 'zh-cn:消息认证码; zh-tw:訊息鑑別碼;'),
Item('message box', 'zh-cn:消息框; zh-tw:訊息方塊;'),
Item('message-oriented', 'zh-cn:面向消息; zh-tw:訊息導向;'),
Item('message-oriented middleware', 'zh-cn:面向消息的中间件; zh-tw:訊息導向中介層;'),
Item('meta-programming', 'zh-cn:元编程; zh-tw:元程式設計;'),
Item('meta-programming', '元編程=>zh-tw:元程式設計; 元編程=>zh-hk:元程式設計; 元編程=>zh-mo:元程式設計;'),
Item('meta-programming', 'zh-cn:超编程; zh-tw:超程式設計;'),
Item('meta-programming', '超編程=>zh-tw:超程式設計; 超編程=>zh-hk:超程式設計; 超編程=>zh-mo:超程式設計; 超編程=>zh-cn:元编程;'),
-- 台灣專業以稱元資料為主
Item('metadata', 'zh-cn:元数据; zh-tw:元資料; zh-hk:元數據;'),
-- 參考文獻:劉青,溫昌斌,海峽兩岸科技名詞差異問題分析與試解,中國科技術語,(3), 2008, 65-69
Item('metal Oxide Semiconductor', 'zh-cn:金属氧化物半导体; zh-tw:金氧半導體;'),
Item('metropolitan Area Network', 'zh-cn:城域网; zh-tw:都會網路;'),
Item('micro-blog', 'zh-cn:微博客; zh-tw:微部落格; zh-hk:微博客;'),
Item('micro-blog', 'zh-cn:微型博客; zh-tw:微型部落格; zh-hk:微型博客;'),
Item('micro-blog', '微網誌=>zh-cn:微博; 微網誌=>zh-sg:微博;'),
Item('microcontroller', 'zh-cn:单片机; zh-tw:單晶片;'),
Item('middleware', 'zh-cn:中间件; zh-tw:中介軟體;'),
Item('midrange', 'zh-cn:中级; zh-tw:中階;'),
Item('midrange', 'zh-cn:中端; zh-tw:中階;'),
Item('MIDP', 'zh-cn:移动信息设备配置文件; zh-tw:行動資訊裝置設定檔; zh-hk:流動資訊器材定義檔;'),
Item('minesweeper', 'zh-cn:扫雷; zh-tw:踩地雷;'),
Item('mixed reality', 'zh-cn:混合现实; zh-sg:混合实境; zh-my:混合实境; zh-tw:混合實境;'),
Item('mobile agent', 'zh-cn:移动代理; zh-tw:行動代理; zh-hk:流動代理;'),
Item('mobile app', 'zh-cn:移动应用; zh-tw:行動應用; zh-hk:流動應用; zh-my:流动应用;'),
Item('mobile broadcasting', 'zh-cn:移动广播; zh-tw:行動廣播; zh-hk:流動廣播; zh-my:流动广播;'),
Item('mobile browser', 'zh-cn:移动浏览器; zh-tw:行動瀏覽器; zh-hk:流動瀏覽器;'),
Item('mobile client', 'zh-cn:移动客户端; zh-tw:行動用戶端; zh-hk:流動用戶端;'),
Item('mobile code', 'zh-cn:移动代码; zh-tw:行動程式碼; zh-hk:流動程式碼;'),
Item('mobile company', 'zh-cn:移动公司; zh-tw:電信公司; zh-hk:流動公司;'),
Item('mobile commerce', 'zh-hans:移动商务; zh-hk:流動商務; zh-tw:行動商務;'),
Item('mobile communication', 'zh-cn:移动通信; zh-tw:行動通訊; zh-hk:流動通訊;'),
Item('mobile computer', 'zh-cn:移动计算机; zh-tw:行動電腦; zh-hk:流動電腦;'),
Item('mobile computing', 'zh-cn:移动计算; zh-tw:行動運算; zh-hk:流動運算;'),
Item('Mobile content management', 'zh-cn:移动内容管理; zh-tw:行動內容管理;'),
Item('mobile data', 'zh-cn:移动数据; zh-tw:行動資料; zh-hk:流動數據;'),
Item('mobile device', 'zh-cn:移动设备; zh-tw:行動裝置; zh-hk:流動裝置;'),
Item('mobile device', '移動設備=>zh-tw:行動裝置; 移動設備=>zh-hk:流動裝置; 移動設備=>zh-mo:流動裝置;'),
Item('mobile device', '移动装置=>zh-tw:行動裝置; 移动装置=>zh-hk:流動裝置; 移动装置=>zh-mo:流動裝置;'),
Item('mobile device', '移動裝置=>zh-tw:行動裝置; 移動裝置=>zh-hk:流動裝置; 移動裝置=>zh-mo:流動裝置;'),
Item('mobile device', '行動設備=>zh-tw:行動裝置; 行動設備=>zh-hk:流動裝置; 行動設備=>zh-mo:流動裝置;'),
Item('mobile device', '流動設備=>zh-tw:行動裝置; 流動設備=>zh-hk:流動裝置; 流動設備=>zh-mo:流動裝置;'),
Item('mobile Internet', 'zh-cn:移动互联网; zh-tw:行動網際網路; zh-hk:流動互聯網;'),
Item('mobile Internet Device', 'zh-cn:移动联网设备; zh-tw:行動網路裝置; zh-hk:行動聯網裝置;'),
Item('mobile network', 'zh-cn:移动网络; zh-tw:行動網路; zh-hk:流動網絡;'),
Item('mobile network operator', 'zh-cn:移动网络运营商; zh-tw:行動網路業者; zh-hk:流動網絡營辦商;'),
Item('mobile operating system', 'zh-cn:移动操作系统; zh-tw:行動作業系統; zh-hk:流動作業系統;'),
Item('mobile operator', 'zh-cn:移动运营商; zh-tw:行動業者; zh-hk:流動營辦商;'),
Item('mobile pay', 'zh-cn:移动支付; zh-tw:行動支付; zh-hk:流動支付;'),
Item('mobile phone', 'zh-cn:移动电话; zh-tw:行動電話; zh-hk:流動電話; zh-my:行动电话;'),
Item('mobile platform', 'zh-cn:移动平台; zh-tw:行動平台; zh-hk:流動平台;'),
Item('mobile product', 'zh-cn:移动产品; zh-tw:行動產品; zh-hk:流動產品;'),
Item('mobile software', 'zh-cn:移动软件; zh-tw:行動軟體; zh-hk:流動軟件;'),
Item('mobile technology', 'zh-cn:移动科技; zh-tw:行動科技; zh-hk:流動科技;'),
Item('mobile technology', 'zh-cn:移动技术; zh-tw:行動技術; zh-hk:流動技術;'),
Item('mobile telecom', 'zh-cn:移动电信; zh-tw:行動電信; zh-hk:流動電訊;'),
Item('mobile telecom operator', 'zh-cn:移动电信运营商; zh-tw:行動電信業者; zh-hk:流動電訊營辦商;'),
Item('mobile television', 'zh-cn:移动电视; zh-tw:行動電視; zh-hk:流動電視;'),
Item('mobile terminal', 'zh-cn:移动终端; zh-tw:行動終端; zh-hk:流動終端;'),
Item('mobile terminal', 'zh-cn:移动端; zh-tw:行動端; zh-hk:流動端;'),
Item('mobile version', 'zh-cn:移动版; zh-tw:行動版; zh-hk:流動版;'),
Item('mobility', 'zh-cn:移动性; zh-tw:行動性; zh-hk:流動性;'),
Item('modem', 'zh-cn:调制解调器; zh-tw:數據機;'),
Item('modem', '調變解調器=>zh-cn:调制解调器; 調變解調器=>zh-sg:调制解调器; 調變解調器=>zh-my:调制解调器;'),
Item('modifier', 'zh-cn:修饰符; zh-tw:修飾詞;'),
Item('module', 'zh-cn:模块; zh-tw:模組;'),
Item('module', '模组=>zh-cn:模块; 模组=>zh-sg:模块; 模组=>zh-my:模块;'),
Item('module', '模塊=>zh-tw:模組; 模塊=>zh-hk:模組; 模塊=>zh-mo:模組;'),
Item('monolithic kernel', 'zh-cn:宏内核; zh-tw:單核心; zh-hk:整塊性核心;'),
Item('most derived class', 'zh-cn:最底层派生类; zh-tw:最末層衍生類別;'),
Item('motherboard', 'zh-cn:主板; zh-tw:主機板;'),
Item('mouse', 'zh:鼠標; zh-cn:鼠标; zh-tw:滑鼠; zh-sg:滑鼠; zh-my:滑鼠;'),
Item('multi-channel network', 'zh-cn:多频道网络; zh-tw:多頻道聯播網;'),
Item('multi-part archive', 'zh-cn:分卷压缩; zh-tw:分割壓縮;'),
Item('multi-tasking', 'zh:多任务;zh-hant:多工;'),
Item('multiagent system', 'zh-cn:多主体系统; zh-tw:多代理系統;'),
Item('multihoming', 'zh-cn:多宿主; zh-tw:內送流量備援容錯機制;'),
Item('Multimedia Messaging Service', 'zh-cn:彩信; zh-sg:多媒体简讯; zh-my:多媒体短讯; zh-tw:多媒體簡訊; zh-hk:多媒體短訊;'),
Item('multithreading', '多緒=>zh-cn:多线程; 多緒=>zh-sg:多线程; 多緒=>zh-my:多线程;'),
Item('mutual information', 'zh-cn:互信息; zh-tw:相互資訊;'),
Item('mutual information', '交互資訊=>zh-cn:互信息; 交互資訊=>zh-sg:互信息; 交互資訊=>zh-my:互信息;'),
Item('mutual information', '交互信息=>zh-tw:相互資訊; 交互信息=>zh-hk:相互資訊; 交互信息=>zh-mo:相互資訊;'),
Item('My Document', 'zh-cn:我的文档; zh-tw:我的文件;'),
{ type = 'text', text = [[
== N ==
]] },
Item('namespace', 'zh-cn:命名空间; zh-tw:命名空間;'),
Item('namespace', '名字空间=>zh-cn:命名空间; 名字空间=>zh-sg:命名空间; 名字空间=>zh-my:命名空间; 名字空間=>zh-tw:命名空間; 名字空間=>zh-hk:命名空間; 名字空間=>zh-mo:命名空間;'),
Item('nanometer', 'zh-hans:纳米; zh-hant:納米; zh-tw:奈米'),
Item('native', '固有=>zh-tw:原生; 固有=>zh-hk:原生; 固有=>zh-mo:原生;'),
Item('narrowband', 'zh-cn:窄带; zh-tw:窄頻;'),
Item('navigation bar', 'zh-cn:导航条; zh-tw:導覽列;'),
Item('near-field communication', 'zh-hk:近場通訊; zh-hans:近场通信; zh-tw:近場通訊;'),
Item('nest', 'zh-cn:嵌套; zh-tw:巢狀;'),
Item('Net disk', 'zh:網盤; zh-cn:网盘; zh-tw:網路硬碟;'),
Item('Netbook', 'zh-cn:上网本; zh-tw:小筆電; zh-hk:NetBook;'),
Item('Netizen', '网民=>zh-tw:網友; 網民=>zh-tw:網友;'),
Item('Netscape Navigator', 'zh-cn:网景导航者; zh-tw:網景領航員;'),
Item('Network', 'zh-cn:网络; zh-tw:網路; zh-hk:網絡;'),
Item('network card', '網路卡=>zh-cn:网卡; 網路卡=>zh-sg:网卡; 網路卡=>zh-my:网卡;'),
Item('network database', 'zh-cn:网状数据库; zh-tw:網狀式資料庫; zh-hk:網絡資料庫;'),
Item('Network Neighbourhood', 'zh-cn:网上邻居; zh-tw:網路上的芳鄰;'),
Item('Network operator', 'zh-cn:网络运营商; zh-tw:網路業者; zh-hk:網絡營辦商;'),
Item('NVIDIA', 'zh-cn:英伟达; zh-tw:輝達;'),
Item('normalization', 'zh-cn:规范化; zh-tw:規格化; zh-hk:規範化;'),
Item('Norton Ghost', 'zh-cn:诺顿克隆精灵; zh-tw:諾頓魅影系統;'),
Item('null list', 'zh-cn:空列表; zh-tw:空串列;'),
Item('null string', 'zh-cn:空串; zh-tw:空字串;'),
{ type = 'text', text = [[
== O ==
]] },
Item('object', '物件=>zh-cn:对象;'),
Item('object code', 'zh-cn:目标代码; zh-tw:目的碼; zh-hk:目標碼;'),
Item('object file', '目的檔案=>zh-cn:目标文件; 目的檔案=>zh-sg:目标文件; 目的檔案=>zh-my:目标文件;'),
Item('object file', 'zh-cn:目标文件; zh-tw:目的檔; zh-hk:目標文件;'),
Item('Object-oriented', 'zh-cn:面向对象; zh-tw:物件導向;'),
Item('Object-oriented programming', 'zh-cn:面向对象编程; zh-tw:物件導向程式設計;'),
Item('octree', 'zh-cn:八叉树; zh-tw:八元樹; zh-hk:八叉樹;'),
Item('Office Shortcut Bar', 'zh-cn:快捷工具栏; zh-tw:快捷列;'),
Item('offline', '脱机=>zh-tw:離線; 脱机=>zh-hk:離線; 脱机=>zh-mo:離線;'),
Item('ones\' complement', 'zh-cn:反码; zh-tw:一補數; zh-hk:一補碼;'),
Item('ones\' complement', '二进制反码=>zh-tw:一補數; 二进制反码=>zh-hk:一補碼; 二进制反码=>zh-mo:一補碼;'),
Item('online', 'zh-cn:在线; zh-tw:線上;'),
Item('online', 'zh:联机; zh-hant:連線;'),
Item('online hard drive', 'zh-cn:网络硬盘; zh-my:网络硬碟; zh-tw:網路硬碟; zh-hk:網絡硬碟;'),
Item('online shopping', 'zh-cn:网络购物; zh-tw:網路購物; zh-hk:網絡購物;'),
Item('online shopping', '网上购物=>zh-tw:網路購物;'),
Item('online shopping', '網上購物=>zh-tw:網路購物;'),
Item('online video', 'zh-cn:在线视频; zh-tw:網路影片; zh-hk:線上影片;'),
-- Item('on the Internet', 'zh-cn:网络; zh-tw:網路; zh-hk:網上;'), 此处严重过度转换:可考虑设-{网上=>zh-tw:網路;}-的单向转换,但更建议延长词长。原理由:依台灣金融相關法律規定已連線為正式用語,非線上
Item('On-Line Transaction Processing', 'zh-cn:联机交易处理; zh-tw:線上異動處理;'),
Item('On-Line Analytical Processing', 'zh-cn:联机分析处理; zh-tw:連線分析處理;'),
Item('open', 'zh-cn:开启; zh-tw:開啟;'),
Item('Open Handset Alliance', 'zh-cn:开放手持设备联盟; zh-tw:開放手機聯盟;'),
Item('Open Mobile Alliance', 'zh-cn:开放移动联盟; zh-tw:開放行動聯盟; zh-hk:流動通訊開放制式聯盟;'),
Item('operand', 'zh-cn:操作数; zh-tw:運算元;'),
Item('operating system', 'zh-cn:操作系统; zh-tw:作業系統;'),
Item('operation object', 'zh-cn:操作对象; zh-tw:運算物件;'),
Item('operator', 'zh-cn:运算符; zh-tw:運算子;'),
Item('operator', '运算子=>zh-cn:运算符; 运算子=>zh-sg:运算符; 运算子=>zh-my:运算符;'),
Item('operator', '運算符=>zh-tw:運算子; 運算符=>zh-hk:運算子; 運算符=>zh-mo:運算子;'),
Item('operator', '操作符=>zh-tw:運算子; 操作符=>zh-hk:運算子; 操作符=>zh-mo:運算子;'),
Item('operator', '操作子=>zh-tw:運算子; 操作子=>zh-hk:運算子; 操作子=>zh-mo:運算子;'),
Item('optimal', 'zh:最优; zh-hant:最佳;'),
Item('optimization', 'zh:最優化; zh-hant:最佳化;'),
Item('optimization', 'zh-hans:优化; zh-hant:最佳化;'),
Item('Optical Network Terminals', 'zh-cn:光网络终端; zh-tw:光纖網路終端;'),
Item('outport', 'zh-cn:导出; zh-tw:匯出;'),
Item('overflow', '上限溢位=>zh-cn:溢出; 上限溢位=>zh-sg:溢出; 上限溢位=>zh-my:溢出;'),
Item('overflow', 'zh-cn:溢出; zh-tw:溢位;'),
Item('overload', 'zh-cn:重载; zh-tw:多載;'),
Item('overload', '過載=>zh-cn:重载; 過載=>zh-sg:重载; 過載=>zh-my:重载;'),
Item('override', 'zh-cn:改写; zh-tw:覆寫;'),
{ type = 'text', text = [[
== P ==
]] },
Item('package', '套件=>zh-cn:包; 套件=>zh-sg:包; 套件=>zh-my:包;'),
Item('package management system', 'zh-cn:软件包管理系统; zh-tw:軟體套件管理系統; zh-hk:軟件套件管理系統;'),
Item('package of software', 'zh-cn:软件包; zh-tw:軟體套件; zh-hk:軟件套件;'),
Item('packet switch', 'zh-cn:分组交换; zh-tw:封包交換;'),
Item('page view', 'zh:訪問量; zh-cn:访问量; zh-tw:瀏覽量;'),
Item('paint', '小畫家=>zh-cn:画图; 小畫家=>zh-sg:画图; 小畫家=>zh-my:画图;'),
Item('palette', 'zh-cn:调色板; zh-tw:調色盤;'),
Item('paradigm', 'zh-cn:范型; zh-tw:範式;'),
Item('parallel', 'zh-cn:并行; zh-tw:並列;'),
Item('parallel computing', 'zh-cn:并行计算; zh-tw:平行計算;'),
Item('parallel port', 'zh-cn:并行端口; zh-tw:並列埠;'),
Item('parallel port', '并口=>zh-tw:並列埠; 并口=>zh-hk:並列埠; 并口=>zh-mo:並列埠;'),
Item('parallel port', '并行端口=>zh-tw:並列埠; 并行端口=>zh-hk:並列埠; 并行端口=>zh-mo:並列埠;'),
Item('parallel port', '并行接口=>zh-tw:並列埠; 并行接口=>zh-hk:並列埠; 并行接口=>zh-mo:並列埠;'),
Item('parameter list', 'zh-cn:参数列表; zh-tw:參數列;'),
Item('parameter list', 'zh-cn:参数表; zh-tw:參數列;'),
Item('parent class', 'zh-cn:父类; zh-tw:父類別;'),
Item('parser', 'zh-cn:分析器; zh-tw:剖析器;'),
Item('partition', 'zh-cn:分区; zh-tw:分割區; zh-hk:分區;'),
Item('paste', 'zh-cn:粘贴; zh-tw:貼上;'),
Item('Password Authentication Protocol', 'zh-cn:密码认证协议; zh-tw:通行碼鑑別協定;'),
Item('patch', 'zh-cn:补丁; zh-tw:修補程式;'),
-- Item('pattern', 'zh-cn:模式; zh-tw:範式;'), 容易過度轉換
Item('Peer-to-Peer', 'zh-cn:点对点; zh-tw:對等;'),
Item('performance', 'zh-cn:性能; zh-tw:效能;'),
Item('permission', '許可權=>zh-cn:权限; 許可權=>zh-sg:权限; 許可權=>zh-my:权限;'),
Item('persistence', 'zh-cn:持久性; zh-tw:永續性;'),
Item('Personal Area Network', 'zh-cn:个人网; zh-tw:個人區域網路;'),
Item('personal digital assistant', 'zh-cn:个人数码助理; zh-tw:個人數位助理; zh-hk:個人數碼助理;'),
Item('personal website', 'zh-cn:个人网站; zh-tw:個人網站; zh-hk:個人網站;'),
Item('Petabyte', 'zh-hans:拍字节; zh-hant:拍位元組;'),
Item('photo', 'zh-cn:照片; zh-tw:相片;'),
Item('photocopy', 'zh-cn:复印; zh-tw:影印;'),
Item('physical layer', 'zh:物理層; zh-cn:物理层; zh-tw:實體層;'),
Item('physical address', 'zh-cn:物理地址; zh-tw:實體位址;'),
Item('physical memory', 'zh-cn:物理内存; zh-tw:實體記憶體;'),
Item('picture viewer', 'zh-cn:图片查看器; zh-tw:圖片檢視器;'),
Item('picture viewer', 'zh:图像浏览器; zh-hant:圖片檢視器;'),
Item('pipeline', 'zh-cn:流水线; zh-tw:管線; zh-hk:管線; zh-mo:管線;'),
Item('pipelining', 'zh-cn:流水线; zh-tw:管線; zh-hk:管線化; zh-mo:管線化;'),
Item('pixel', '畫素=>zh-cn:像素; 畫素=>zh-sg:像素; 畫素=>zh-my:像素; 畫素=>zh-hk:像素; 畫素=>zh-mo:像素;'),
Item('pixel', '画素=>zh-cn:像素; 画素=>zh-sg:像素; 画素=>zh-my:像素; 画素=>zh-hk:像素; 画素=>zh-mo:像素;'),
Item('placeholder', 'zh-cn:占位符; zh-tw:預留位置;'),
Item('Plug and Play', 'zh-cn:即插即用; zh-tw:隨插即用;'),
Item('plug-in', 'zh-cn:插件; zh-tw:外掛程式;'),
Item('plug-in', '外掛模組=>zh-cn:插件; 外掛模組=>zh-sg:插件; 外掛模組=>zh-my:插件;'),
Item('podcast', 'zh-cn:播客; zh-tw:播客;'),
Item('point and click', '点选=>zh-cn:点击; 点选=>zh-sg:点击; 点选=>zh-my:点击; 点选=>zh-hk:點擊; 点选=>zh-mo:點擊;'),
Item('point and click', '點選=>zh-cn:点击; 點選=>zh-sg:点击; 點選=>zh-my:点击; 點選=>zh-hk:點擊; 點選=>zh-mo:點擊;'),
Item('pointer', 'zh-cn:指针; zh-tw:指標;'),
Item('polymorphism', 'zh-cn:多态; zh-tw:多型;'),
Item('Popups', 'zh-cn:弹出窗口; zh-tw:彈出式視窗;'),
Item('port', 'zh-cn:端口; zh-tw:埠;'),
-- Item('port', '接口=>zh-tw:埠; 接口=>zh-hk:埠; 接口=>zh-mo:埠;'), 容易過度轉換
Item('port', '通訊埠=>zh-cn:端口;'),
Item('port forwarding', 'zh-cn:端口转发; zh-tw:通訊埠轉發;'),
Item('portable', 'zh-cn:便携式; zh-tw:可攜式;'),
Item('portable', '可携式=>zh-cn:便携式; 可携式=>zh-sg:便携式; 可携式=>zh-my:便携式;'),
Item('portable', '便攜式=>zh-tw:可攜式; 便攜式=>zh-hk:可攜式; 便攜式=>zh-mo:可攜式;'),
Item('portable', '便携=>zh-tw:可攜式; 便携=>zh-hk:可攜式; 便携=>zh-mo:可攜式;'),
Item('portable', '便攜=>zh-tw:可攜式; 便攜=>zh-hk:可攜式; 便攜=>zh-mo:可攜式;'),
Item('portable application', 'zh-cn:绿色软件; zh-tw:可攜式軟體; zh-hk:可攜式軟件;'),
Item('portable application', '綠色軟件=>zh-tw:可攜式軟體; 綠色軟件=>zh-hk:可攜式軟件; 綠色軟件=>zh-mo:可攜式軟件;'),
Item('portable application', '綠色軟體=>zh-tw:可攜式軟體; 綠色軟體=>zh-hk:可攜式軟件; 綠色軟體=>zh-mo:可攜式軟件;'),
Item('portable application', '便携软件=>zh-tw:可攜式軟體; 便携软件=>zh-hk:可攜式軟件; 便携软件=>zh-mo:可攜式軟件;'),
Item('portable edition', 'zh-cn:便携版; zh-tw:可攜式版本;'),
Item('portable hard drive', 'zh-cn:移动硬盘; zh-tw:行動硬碟; zh-hk:流動硬碟;'),
Item('Portable Document Format', 'zh-cn:可移植文档格式; zh-tw:可攜式文件格式;'),
Item('portal', 'zh-cn:门户系统; zh-tw:入口網站; zh-hk:入門系統;'),
Item('portal', 'zh-cn:门户网站; zh-tw:入口網站; zh-hk:入門網站;'),
Item('post', 'zh-cn:帖子; zh-sg:贴文; zh-my:贴文; zh-tw:貼文;'),
Item('power bank', 'zh-cn:移动电源; zh-tw:行動電源; zh-hk:流動充電器'),
Item('preference', '预置=>zh-tw:偏好設定; 预置=>zh-hk:參數設置; 预置=>zh-mo:參數設置;'),
Item('preference settings', 'zh-cn:首选项; zh-my:偏好设置; zh-tw:偏好設定; zh-hk:參數設置;'),
Item('prefix', 'zh-cn:前缀; zh-tw:字首;'),
Item('presentation', 'zh-cn:演示稿; zh-tw:簡報;'),
Item('print', 'zh-cn:打印; zh-tw:列印;'),
Item('print preview', 'zh-cn:打印预览; zh-tw:預覽列印;'),
Item('printer', 'zh:打印機; zh-cn:打印机; zh-tw:印表機;'),
Item('procedural generation', '程序化生成=>zh-cn:过程生成; 程序化生成=>zh-sg:过程生成; 程序化生成=>zh-my:过程生成;'),
Item('procedural programming', 'zh-cn:过程式; zh-tw:程序式;'),
Item('procedural programming', 'zh-cn:过程化; zh-tw:程序化;'),
Item('procedural programming', 'zh-cn:面向过程; zh-tw:程序導向;'),
Item('process', '連作=>zh-cn:进程; 連作=>zh-sg:进程; 連作=>zh-my:进程;'),
Item('process', '處理程序=>zh-cn:进程; 處理程序=>zh-sg:进程; 處理程序=>zh-my:进程;'),
Item('process', '进程=>zh-tw:行程; 进程=>zh-hk:行程; 进程=>zh-mo:行程;'),
-- Item('process', '行程=>zh-cn:进程; 行程=>zh-sg:进程; 行程=>zh-my:进程;'), 容易過度轉換
-- Item('process', '過程=>zh-cn:进程; 過程=>zh-sg:进程; 過程=>zh-my:进程;'), 容易過度轉換
Item('process control block', 'zh-cn:进程控制块; zh-tw:過程控制段; zh-hk:行程控制表;'),
Item('process group', 'zh-cn:进程组; zh-tw:行程群組;'),
Item('product key', 'zh-cn:产品密钥; zh-tw:產品金鑰;'),
Item('profile', 'zh-cn:配置文件; zh-tw:設定檔;'),
Item('program', 'zh-cn:程序; zh-tw:程式;'),
Item('programmer', 'zh-cn:程序编写员; zh-tw:程式設計師;'),
Item('programmer', 'zh:程序員; zh-cn:程序员; zh-tw:程式設計師;'),
Item('programmable', 'zh:可編程; zh-cn:可编程; zh-tw:可程式化;'),
Item('programmable', '可規化=>zh-cn:可编程; 可規化=>zh-sg:可编程; 可規化=>zh-my:可编程;'),
Item('programming language', 'zh-cn:编程语言; zh-tw:程式語言;'),
Item('programming language', '程式语言=>zh-cn:编程语言; 程式语言=>zh-sg:编程语言; 程式语言=>zh-my:编程语言;'),
Item('programming language', '编程語言=>zh-tw:程式語言; 编程語言=>zh-hk:程式語言; 编程語言=>zh-mo:程式語言;'),
Item('programming language', '編程语言=>zh-tw:程式語言; 編程语言=>zh-hk:程式語言; 編程语言=>zh-mo:程式語言;'),
Item('programming language', '編程語言=>zh-tw:程式語言; 編程語言=>zh-hk:程式語言; 編程語言=>zh-mo:程式語言;'),
Item('Programming paradigm', 'zh-cn:编程范型; zh-tw:程式設計範式;'),
-- Item('project', 'zh-cn:工程; zh-tw:專案;'), 容易過度轉換
Item('project', 'zh-cn:项目; zh-tw:專案;'),
Item('project', '計畫=>zh-cn:项目; 計畫=>zh-sg:项目; 計畫=>zh-my:计划; 計畫=>zh-hk:計劃; 計畫=>zh-mo:計劃;'),
Item('project page', 'zh-cn:项目页; zh-tw:計畫頁;'),
Item('protocol', 'zh:協議; zh-cn:协议; zh-tw:協定;'),
Item('prototype-based programming', 'zh-cn:基于原型的编程; zh-tw:原型程式設計;'),
Item('proximity sensor', 'zh-cn:接近传感器; zh-tw:鄰近感測器;'),
Item('Pseudocode', 'zh-cn:伪代码; zh-tw:虛擬碼; zh-hk:偽代碼;'),
Item('pattern recognition', 'zh:模式識別; zh-cn:模式识别; zh-tw:圖型識別;'),
Item('Public land mobile network', 'zh-cn:公共陆基移动网; zh-tw:公用陸上行動網路; zh-hk:公地流動網路;'),
Item('pull-down lists', 'zh-cn:下拉列表; zh-tw:下拉式清單;'),
-- 維基百科內建功能
Item('purge', '刷新缓存=>zh-tw:清除快取; 刷新缓存=>zh-hk:清除快取; 刷新缓存=>zh-mo:清除快取;'),
Item('purge', 'zh-cn:清理缓存; zh-tw:清除快取;'),
Item('push', 'zh-cn:推送; zh-tw:推播;'),
{ type = 'text', text = [[
== Q ==
]] },
Item('QR code', 'QR code=>zh-cn:QR码; QR code=>zh-sg:QR码; QR code=>zh-my:QR码; QR code=>zh-hk:QR碼; QR code=>zh-mo:QR碼;'),
Item('QR code', 'QRcode=>zh-cn:QR码; QRcode=>zh-sg:QR码; QRcode=>zh-my:QR码; QRcode=>zh-hk:QR碼; QRcode=>zh-mo:QR碼;'),
Item('QR code', '行動條碼=>zh-cn:QR码; 行動條碼=>zh-sg:QR码; 行動條碼=>zh-my:QR码; 行動條碼=>zh-hk:QR碼; 行動條碼=>zh-mo:QR碼;'),
Item('queue', 'zh-cn:队列; zh-tw:佇列;'),
Item('quadtree', 'zh-cn:四叉树; zh-tw:四元樹; zh-hk:四叉樹;'),
Item('quality', 'zh-cn:质量; zh-tw:品質; zh-hk:質素;'),
Item('quality', '品质=>zh-cn:质量; 品质=>zh-sg:质量; 品质=>zh-my:质量; 品质=>zh-hk:質素; 品质=>zh-mo:質素;'),
Item('quality', '质素=>zh-cn:质量; 质素=>zh-sg:质量; 质素=>zh-my:质量; 质素=>zh-tw:品質;'),
Item('quality', '質量=>zh-tw:品質; 質量=>zh-hk:質素; 質量=>zh-mo:質素;'),
{ type = 'text', text = [[
== R ==
]] },
Item('radio button', 'zh-cn:单选按钮; zh-tw:無線電鈕;'),
Item('radio-frequency identification', 'zh-cn:射频识别; zh-tw:無線射頻辨識; zh-hk:無線射頻辨識; zh-sg:射频识别;'),
Item('random-access memory', 'zh-cn:随机存储器; zh-tw:隨機存取記憶體'),
Item('random number', 'zh-cn:随机数; zh-tw:亂數;'),
Item('readme', 'zh-cn:自述文件; zh-tw:讀我檔案;'),
Item('read-only', 'zh-cn:只读; zh-tw:唯讀;'),
Item('read-only memory', 'zh-cn:只读存储器; zh-tw:唯讀記憶體;'),
Item('real mode', 'zh-cn:实模式; zh-tw:真實模式;'),
Item('real mode', '真实模式=>zh-cn:实模式; 真实模式=>zh-sg:实模式; 真实模式=>zh-my:实模式;'),
Item('real mode', '實模式=>zh-tw:真實模式; 實模式=>zh-hk:真實模式; 實模式=>zh-mo:真實模式;'),
Item('real-time', '实时=>zh-tw:即時; 实时=>zh-hk:即時; 实时=>zh-mo:即時;'),
Item('reboot', 'zh-cn:重启; zh-tw:重新啟動;'),
Item('reboot', '重新開機=>zh-cn:重启; 重新開機=>zh-sg:重启; 重新開機=>zh-my:重启;'),
Item('recognition', 'zh-cn:识别; zh-tw:辨識;'),
Item('recover', '回復=>zh-cn:恢复; 回復=>zh-sg:恢复; 回復=>zh-my:恢复;'),
Item('recovery disc', 'zh-cn:恢复光盘; zh-tw:還原光碟;'),
Item('recovery record', 'zh-cn:恢复记录; zh-tw:恢復記錄; zh-hk:修復記錄;'),
Item('recursion', 'zh-cn:递归; zh-tw:遞迴; zh-hk:遞歸;'),
Item('Recycle Bin', 'zh-cn:回收站; zh-tw:資源回收筒;'),
Item('Red Screen', 'zh-hant:紅屏; zh-cn:红屏; zh-tw:紅白畫面; zh-hk:紅畫面;'),
Item('Red Screen of Death', 'zh-hant:紅屏死機; zh-cn:红屏死机; zh-tw:紅白當機; zh-hk:紅畫面死機;'),
Item('Red Screen of Death', '紅屏當機=>zh-cn:红屏死机; 紅屏當機=>zh-tw:紅白當機; 紅屏當機=>zh-hk:紅畫面死機;'),
Item('redirect', 'zh-cn:重定向; zh-tw:重新導向;'),
Item('redirect page', 'zh-cn:重定向页; zh-tw:重新導向頁面;'),
Item('redirect page', '重定向頁=>zh-tw:重新導向頁面; 重定向頁=>zh-hk:重新導向頁面; 重定向頁=>zh-mo:重新導向頁面;'),
Item('redirect page', '重定向页面=>zh-tw:重新導向頁面; 重定向页面=>zh-hk:重新導向頁面; 重定向页面=>zh-mo:重新導向頁面;'),
Item('redirect page', '重定向頁面=>zh-tw:重新導向頁面; 重定向頁面=>zh-hk:重新導向頁面; 重定向頁面=>zh-mo:重新導向頁面;'),
Item('reference', 'zh-cn:引用; zh-tw:參照;'),
-- Item('reference', '參考=>zh-cn:引用; 參考=>zh-sg:引用; 參考=>zh-my:引用;'), 容易過度轉換
Item('dereference', 'zh-cn:解引用; zh-tw:解除參照;'),
Item('refresh', 'zh-cn:刷新; zh-tw:重新整理;'),
Item('refresh rate', 'zh-cn:刷新率; zh-tw:重新整理頻率;'),
Item('register', 'zh-cn:寄存器; zh-tw:暫存器;'),
Item('registry', 'zh-cn:注册表; zh-tw:登錄檔;'),
Item('regular expression', 'zh-cn:正则表达式; zh-tw:正規表示式; zh-hk:正則表達式;'),
Item('regular language', 'zh-cn:正则语言; zh-tw:正規語言; zh-hk:正則語言;'),
Item('regular language', '正规语言=>zh-cn:正则语言; 正规语言=>zh-sg:正则语言; 正规语言=>zh-my:正则语言;'),
Item('reinstallation', 'zh-cn:重装; zh-tw:重新安裝;'),
Item('relational', '關聯=>zh-cn:关系; 關聯=>zh-sg:关系; 關聯=>zh-my:关系;'),
Item('relational database', 'zh-cn:关系数据库; zh-tw:關聯式資料庫;'),
Item('release', '釋出=>zh-cn:发布; 釋出=>zh-sg:发布; 釋出=>zh-my:发布;'),
-- Item('release', 'zh-cn:发行; zh-tw:釋出;'),
Item('remote', 'zh-cn:远程; zh-tw:遠端;'),
Item('remote desktop protocol', 'zh-cn:远程桌面协议; zh-tw:遠端桌面協定;'),
Item('remote procedure call', 'zh-cn:远程过程调用; zh-tw:遠端程序呼叫;'),
-- 「可移动磁盘」對應「抽取式磁碟」(來自微軟官網)
Item('removable', 'zh-cn:可移动; zh-tw:抽取式;'),
Item('rename', 'zh-cn:重命名; zh-tw:重新命名;'),
Item('render', 'zh-cn:渲染; zh-tw:彩現;'),
Item('repeating group', 'zh-cn:重复组; zh-tw:重複群;'),
Item('reply', 'zh-hans:回复; zh-hant:回覆;'),
Item('reply', 'zh-hans:答复; zh-hant:答覆;'),
Item('Republic of Gamers', 'zh-cn:玩家国度; zh-tw:玩家共和國;'),
Item('reset', 'zh-cn:重置; zh-tw:重設;'),
Item('resolution', 'zh-cn:分辨率; zh-tw:解析度; zh-hk:解像度;'),
Item('response', '响应=>zh-tw:回應;'),
Item('Rich Internet application', 'zh-cn:丰富互联网应用程序; zh-tw:多樣化網際網路應用程式; zh-hk:多樣化互聯網應用程式;'),
Item('rollback', 'zh-cn:回滚; zh-tw:轉返;'),
Item('routine', 'zh-cn:例程; zh-tw:常式;'),
Item('run', '运行=>zh-tw:執行;运行=>zh-hk:執行;运行=>zh-mo:執行;'),
Item('running in the background', 'zh-cn:后台运行;zh-tw:背景執行;'),
{ type = 'text', text = [[
== S ==
]] },
Item('sample', 'zh-cn:示例; zh-tw:範例;'),
Item('sampling rate', 'zh-cn:采样率; zh-tw:取樣率;'),
Item('sampling rate', '取樣頻率=>zh-cn:采样率; 取樣頻率=>zh-sg:采样率; 取樣頻率=>zh-my:采样率; 取樣頻率=>zh-hk:取樣率; 取樣頻率=>zh-mo:取樣率;'),
Item('SanDisk', 'zh-cn:闪迪; zh-tw:新帝; zh-hk:SanDisk;'),
Item('SanDisk', 'zh-hans:新帝国; zh-hant:新帝國;'), -- 防止过度转换
Item('save', '保存=>zh-tw:儲存; 保存=>zh-hk:儲存; 保存=>zh-mo:儲存;'),
Item('scanner', 'zh:掃描儀; zh-cn:扫描仪; zh-tw:掃描器;'),
Item('schedule', 'zh-cn:调度; zh-tw:排程;'),
Item('scheduler', 'zh-cn:调度器; zh-tw:排程器;'),
Item('screen', 'zh-cn:屏幕; zh-tw:螢幕; zh-hk:螢幕;'),
Item('screensaver', 'zh-cn:屏幕保护程序; zh-tw:螢幕保護裝置; zh-hk:螢幕保護裝置;'),
Item('screenshot', 'zh-cn:截屏; zh-tw:螢幕擷取; zh-hk:螢幕擷取;'),
Item('script', 'zh:腳本; zh-cn:脚本; zh-tw:指令碼;'),
Item('scripting language', 'zh:腳本語言; zh-cn:脚本语言; zh-tw:手稿語言;'),
Item('scroll', 'zh-cn:滚动; zh-tw:捲動;'),
Item('scroll bar', 'zh-cn:滚动条; zh-tw:捲軸;'),
Item('scroll bar', 'zh-cn:滚动栏; zh-tw:捲軸;'),
Item('scroll box', 'zh-cn:滚动框; zh-tw:捲動方塊;'),
Item('SDK', 'zh-cn:软件开发工具包; zh-tw:軟體開發套件; zh-hk:軟件開發套件;'),
Item('search', 'zh-cn:搜索; zh-tw:搜尋;'),
Item('search box', 'zh-cn:搜索框; zh-tw:搜尋方塊;'),
Item('search key', 'zh-cn:搜索关键字; zh-tw:搜尋鍵碼;'),
Item('second normal form', 'zh-cn:第二范式; zh-tw:第二正規化;'),
Item('sector', 'zh-cn:扇区; zh-tw:磁區;'),
Item('Secure Sockets Layer', 'zh-cn:安全套接层; zh-tw:安全通訊協定;'),
Item('security software', 'zh:安全軟件; zh-cn:安全软件; zh-tw:安全軟體; zh-hk:保安軟件;'),
Item('Semantic Web', 'zh-cn:语义网; zh-tw:語意網;'),
Item('semantics', 'zh-cn:语义; zh-tw:語意;'),
Item('semaphore', 'zh:信號量; zh-cn:信号量; zh-tw:號誌; zh-hk:訊號量;'),
Item('send', 'zh:發送; zh-cn:发送; zh-tw:傳送;'),
Item('send SMS', 'zh-cn:发短信; zh-sg:发简讯; zh-my:发短讯; zh-tw:傳簡訊; zh-hk:傳短訊;'),
Item('sensor', 'zh:傳感器; zh-cn:传感器; zh-tw:感測器;'),
Item('Sequencing', 'zh-cn:测序; zh-tw:定序;'),
Item('Serial computing', 'zh-cn:串行计算; zh-tw:序列計算;'),
Item('Serial port', 'zh-hans:串行端口; zh-hant:序列埠;'),
Item('Serial port', 'zh-hans:串口;zh-hant:序列埠;'),
Item('server', 'zh:服務器; zh-cn:服务器; zh-my:伺服器; zh-tw:伺服器;'),
Item('server message block', 'zh-cn:服务器消息块; zh-tw:伺服器訊息區塊;'),
Item('server-side', 'zh-cn:服务端; zh-tw:伺服器端;'),
Item('server-side', '伺服端=>zh-cn:服务端; 伺服端=>zh-sg:服务端;'),
Item('server-side', '服務端=>zh-tw:伺服器端; 服務端=>zh-hk:伺服器端; 服務端=>zh-mo:伺服器端;'),
Item('service framework', 'zh-cn:服务框架; zh-tw:服務架構;'),
Item('session', 'zh-cn:会话; zh-tw:對談;'),
Item('Session Identity', 'zh-cn:会话标识; zh-tw:交談識別碼;'),
Item('session ID', 'zh-cn:会话标识; zh-tw:交談識別碼;'),
Item('session hijacking', 'zh-cn:会话劫持; zh-tw:連線劫持;'),
Item('setting', 'zh-cn:设置; zh-tw:設定; zh-hk:設置;'),
Item('set-top box', 'zh-cn:机顶盒; zh-tw:機上盒; zh-hk:機頂盒;'),
Item('share', 'zh-cn:共享; zh-tw:共享; zh-hk:共用;'),
Item('shared folder', '分享資料夾=>zh-cn:共享文件夹; 分享資料夾=>zh-sg:共享文件夹; 分享資料夾=>zh-my:共享文件夹; 分享資料夾=>zh-tw:共用資料夾;'),
Item('short video', 'zh-cn:短视频; zh-tw:短影音; zh-hk:短影音;'),
Item('shortcut', 'zh-cn:快捷方式; zh-tw:捷徑;'),
Item('shortcut key', 'zh-cn:快捷键; zh-tw:快速鍵;'),
Item('Single Link', 'zh-cn:单通道; zh-tw:單連結;'),
Item('signal', 'zh-cn:信号; zh-tw:訊號;'),
Item('signal', '信號=>zh-tw:訊號; 信號=>zh-hk:訊號; 信號=>zh-mo:訊號;'),
Item('signal', '讯号=>zh-cn:信号; 讯号=>zh-sg:信号; 讯号=>zh-my:信号;'),
Item('signature', 'zh-cn:签名; zh-tw:簽章;'),
Item('simulated reality', 'zh-cn:模拟现实; zh-tw:模擬實境;'),
Item('single sign-on', 'zh-cn:单点登录; zh-tw:單一登入;'),
Item('Site Identity Button', 'zh-cn:站点标识按钮; zh-tw:網站識別鈕;'),
Item('sixth normal form', 'zh-cn:第六范式; zh-tw:第六規格化;'),
Item('skin', '皮肤=>zh-tw:外觀; 皮肤=>zh-hk:佈景主題; 皮肤=>zh-mo:佈景主題;'),
Item('slider', 'zh-cn:滑块; zh-tw:滾軸;'),
Item('smart', 'zh-cn:智能; zh-sg:智慧; zh-tw:智慧型; zh-hk:智能;'),
Item('smart card', 'zh-cn:智能卡; zh-sg:智慧卡; zh-tw:智慧卡; zh-hk:智能卡;'),
Item('Smart speaker', 'zh-cn:智能音箱; zh-tw:智慧型喇叭; zh-hk:智能音箱;'),
Item('smart television', 'zh-cn:智能电视; zh-tw:智慧型電視; zh-hk:智能電視;'),
Item('smartphone', 'zh-hans:智能电话; zh-hant:智能手機; zh-cn:智能手机; zh-tw:智慧型手機; zh-hk:智能電話;'),
Item('smartwatch', 'zh-cn:智能手表; zh-tw:智慧型手錶; zh-hk:智能手錶; zh-sg:智慧手表;'),
Item('SMS', 'zh-cn:短信; zh-sg:简讯; zh-my:短讯; zh-tw:簡訊; zh-hk:短訊;'),
Item('SMS', '短消息=>zh-sg:简讯; 短消息=>zh-my:短讯; 短消息=>zh-tw:簡訊; 短消息=>zh-hk:短訊; 短消息=>zh-mo:短訊;'),
Item('SMS', '短信息=>zh-sg:简讯; 短信息=>zh-my:短讯; 短信息=>zh-tw:簡訊; 短信息=>zh-hk:短訊; 短信息=>zh-mo:短訊;'),
Item('Snowden', 'zh-cn:斯诺登; zh-tw:史諾登; zh-hk:斯諾登;'),
Item('social media', 'zh-cn:社交媒体;zh-tw:社群媒體;zh-hk:社交媒體;'),
Item('social network', 'zh-cn:社交网络; zh-tw:社群網路; zh-hk:社交網絡;'),
Item('social networking site', 'zh-cn:社交网站; zh-tw:社群網站; zh-hk:社交網站;'),
Item('socket', 'zh-cn:套接字; zh-tw:通訊端;'),
Item('socket', '通訊端點=>zh-cn:套接字; 通訊端點=>zh-my:套接字; 通訊端點=>zh-sg:套接字;'),
Item('sockets layer', 'zh-cn:套接层; zh-tw:通訊層;'),
Item('software', 'zh-cn:软件; zh-tw:軟體; zh-hk:軟件;'),
Item('software process', 'zh-cn:软件过程; zh-tw:軟體流程; zh-hk:軟件流程;'),
Item('solid archive', 'zh-cn:固实压缩; zh-tw:結實壓縮;'),
Item('Sony Mobile', 'zh-cn:索尼移动; zh-tw:索尼行動; zh-hk:索尼流動;'),
Item('Sony Mobile Communications', 'zh-cn:索尼移动通信; zh-tw:索尼行動通訊; zh-hk:索尼流動通訊;'),
Item('Sound card', 'zh-cn:声卡; zh-tw:音效卡;'),
Item('source code', 'zh-cn:源代码; zh-sg:原始码; zh-tw:原始碼;'),
Item('source code', '源代碼=>zh-sg:原始码; 源代碼=>zh-my:原始码; 源代碼=>zh-tw:原始碼; 源代碼=>zh-hk:原始碼; 源代碼=>zh-mo:原始碼;'),
Item('source code', '源码=>zh-sg:原始码; 源码=>zh-my:原始码; 源码=>zh-tw:原始碼; 源码=>zh-hk:原始碼; 源码=>zh-mo:原始碼;'),
Item('source code', '源碼=>zh-sg:原始码; 源碼=>zh-my:原始码; 源碼=>zh-tw:原始碼; 源碼=>zh-hk:原始碼; 源碼=>zh-mo:原始碼;'),
Item('source file', 'zh-cn:源文件; zh-tw:原始檔;'),
Item('spreadsheet', 'zh-cn:电子表格; zh-tw:電子試算表;'),
Item('spreadsheet', '试算表=>zh-cn:表格; 试算表=>zh-sg:表格; 试算表=>zh-my:表格;'),
Item('spreadsheet', '試算表=>zh-cn:表格; 試算表=>zh-sg:表格; 試算表=>zh-my:表格;'),
Item('SSD', 'zh-cn:固态盘; zh-tw:固態硬碟;'),
Item('statement', 'zh-cn:语句; zh-tw:語句; zh-hk:陳述式;'),
Item('stack', 'zh-cn:堆栈; zh-tw:堆疊;'),
Item('stack frame', 'zh-cn:堆栈帧; zh-tw:堆疊框; zh-hk:堆疊幀;'),
Item('stack frame', '栈帧=>zh-tw:堆疊框; 栈帧=>zh-hk:堆疊幀; 栈帧=>zh-mo:堆疊幀;'),
Item('stack-oriented', 'zh-cn:面向堆栈; zh-tw:堆疊導向;'),
Item('standard definition', 'zh-cn:标清; zh-tw:標準畫質; zh-hk:標清;'),
Item('static typing', 'zh-cn:静态类型; zh-tw:靜態型別;'),
Item('status bar', 'zh-cn:状态栏; zh-tw:狀態列;'),
Item('sticky keys', 'zh-cn:粘滞键; zh-tw:相黏鍵;'),
Item('storage', 'zh-cn:存储; zh-tw:儲存;'),
Item('storage', '存儲=>zh-tw:儲存; 存儲=>zh-hk:儲存; 存儲=>zh-mo:儲存;'),
Item('stored procedure', 'zh-cn:存储程序; zh-tw:儲存程序;'),
Item('stored procedure', '預存程序=>zh-cn:存储程序; 預存程序=>zh-sg:存储程序; 預存程序=>zh-my:存储程序;'),
Item('stored procedure', '存儲程序=>zh-tw:儲存程序; 存儲程序=>zh-hk:儲存程序; 存儲程序=>zh-mo:儲存程序;'),
Item('stored procedure', '存储过程=>zh-tw:儲存程序; 存储过程=>zh-hk:儲存程序; 存储过程=>zh-mo:儲存程序;'),
Item('stored procedure', '存儲過程=>zh-tw:儲存程序; 存儲過程=>zh-hk:儲存程序; 存儲過程=>zh-mo:儲存程序;'),
Item('stream', '串流=>zh-cn:流; 串流=>zh-sg:流; 串流=>zh-my:流;'),
Item('stream', '流式=>zh-tw:串流; 流式=>zh-hk:串流; 流式=>zh-mo:串流;'),
Item('stream cipher', 'zh-cn:流密码; zh-tw:串流加密法;'),
Item('string', 'zh-cn:字符串; zh-tw:字串;'),
Item('strong typing', 'zh-cn:强类型; zh-tw:強型別;'),
Item('submit', '送出=>zh-cn:提交; 送出=>zh-sg:提交; 送出=>zh-my:提交;'),
Item('subnet', 'zh-cn:子网; zh-tw:子網路; zh-hk:子網絡;'),
Item('subnet mask', 'zh-cn:子网掩码; zh-tw:子網路遮罩; zh-hk:子網絡遮罩;'),
Item('subroutine', 'zh-cn:子例程; zh-tw:次常式;'),
Item('suffix', 'zh-cn:后缀; zh-tw:字尾;'),
-- 有可能過度轉換,編輯時須注意
Item('support', 'zh-cn:支持; zh-tw:支援;'),
Item('Sun Microsystems', 'zh-cn:Sun微系统; zh-tw:昇陽電腦; zh-hk:太陽電腦;'),
Item('super computer', 'zh-cn:超级计算机; zh-tw:超級電腦;'),
Item('syntax highlighting', 'zh-cn:语法高亮; zh-tw:語法突顯;'),
Item('syntax highlighting', '語法凸顯=>zh-cn:语法高亮; 語法凸顯=>zh-sg:语法高亮; 語法凸顯=>zh-my:语法高亮;'),
Item('syntax highlighting', '语法高亮度=>zh-tw:語法突顯; 语法高亮度=>zh-hk:語法突顯; 语法高亮度=>zh-mo:語法突顯;'),
Item('syntax highlighting', '語法高亮度=>zh-tw:語法突顯; 語法高亮度=>zh-hk:語法突顯; 語法高亮度=>zh-mo:語法突顯;'),
Item('system (format)', '制式=>zh-tw:格式; 制式=>zh-hk:格式; 制式=>zh-mo:格式;'),
Item('System on a chip, SoC', 'zh-cn:单片系统; zh-tw:單晶片系統;'),
{ type = 'text', text = [[
== T ==
]] },
Item('tab', 'zh-cn:标签页; zh-tw:分頁;'),
Item('tab', 'zh-cn:选项卡; zh-tw:索引標籤;'),
Item('tail recursion', 'zh-cn:尾部递归; zh-tw:尾端遞迴;'),
Item('target', 'zh-cn:目标软件; zh-tw:目標軟體; zh-hk:目標軟件;'),
Item('target user', 'zh-cn:目标用户; zh-tw:目標使用者;'),
Item('task bar', 'zh-cn:任务栏; zh-tw:工作列;'),
Item('task manager', 'zh-cn:任务管理器; zh-tw:工作管理員;'),
Item('task switch', 'zh-cn:任务切换; zh-tw:工作切換;'),
Item('template', '樣板=>zh-cn:模板; 樣板=>zh-sg:模板; 樣板=>zh-my:模板; 樣板=>zh-tw:模板; 樣板=>zh-hk:模板; 樣板=>zh-mo:模板;'),
Item('Terabyte', 'zh-hans:太字节; zh-hant:兆位元組;'),
Item('terminator', 'zh-cn:终结器; zh-tw:終端子;'),
Item('ternary linked list', 'zh-cn:三叉链表; zh-tw:三元連結串列;'),
Item('ternary linked list', '三叉鏈表=>zh-tw:三元連結串列; 三叉鏈表=>zh-hk:三元連結串列; 三叉鏈表=>zh-mo:三元連結串列;'),
Item('ternary search tree', 'zh-cn:三叉搜索树; zh-tw:三元搜尋樹; zh-hk:三叉搜尋樹;'),
Item('ternary search tree', '三叉查找树=>zh-tw:三元搜尋樹; 三叉查找树=>zh-hk:三叉搜尋樹; 三叉查找树=>zh-mo:三叉搜尋樹;'),
Item('ternary tree', 'zh-cn:三叉树; zh-tw:三元樹; zh-hk:三叉樹;'),
-- Item('terrestrial', '地面=>zh-tw:無線; 地面=>zh-hk:無線; 地面=>zh-mo:無線;'), 易过度转换
Item('terrestrial television', 'zh-cn:地面电视; zh-tw:無線電視; zh-hk:地面電視;'),
Item('terrestrial broadcasting', 'zh-cn:地面广播; zh-tw:無線廣播; zh-hk:地面廣播;'),
Item('text', '文本=>zh-tw:文字; 文本=>zh-hk:文字; 文本=>zh-mo:文字;'),
Item('textbox', 'zh-cn:文本框; zh-tw:文字方塊; zh-hk:文本框;'),
Item('text editor', 'zh-cn:文本编辑器; zh-tw:文字編輯器;'),
Item('text file', 'zh-cn:文本文件; zh-tw:文字檔案;'),
Item('third normal form', 'zh-cn:第三范式; zh-tw:第三正規化;'),
Item('threads', 'zh-cn:线程; zh-tw:執行緒; zh-hk:線程;'),
Item('throw', 'zh-cn:抛出; zh-tw:丟擲; zh-hk:投擲;'),
Item('thumbnail', 'zh-cn:缩略图; zh-tw:縮圖;'),
Item('timeout', 'zh-hans:超时; zh-hant:逾時;'),
Item('title bar', 'zh-cn:标题栏; zh-tw:標題列;'),
Item('token', 'zh-cn:权标; zh-tw:符記;'),
Item('token', 'zh-cn:令牌; zh-tw:權杖;'),
Item('toolbar', 'zh-cn:工具栏; zh-tw:工具列;'),
Item('touch', 'zh-cn:触摸; zh-tw:輕觸;'),
Item('touchscreen', 'zh-cn:触摸屏; zh-tw:觸控式螢幕; zh-hk:輕觸式螢幕;'),
Item('touchscreen', 'zh-cn:触屏; zh-tw:觸控螢幕; zh-hk:輕觸螢幕;'),
Item('TouchPad', 'zh-cn:触摸板; zh-tw:觸控板;'),
Item('track', 'zh-cn:磁道; zh-tw:磁軌;'),
Item('traditional (Chinese)', '正體=>zh-cn:繁体; 正體=>zh-sg:繁体; 正體=>zh-my:繁体; 正體=>zh-hk:繁體; 正體=>zh-mo:繁體;'),
Item('Trinitron', 'zh-cn:特丽珑; zh-tw:特麗霓虹;'),
Item('troubleshooting', 'zh-cn:疑难解答; zh-tw:疑難排解;'),
Item('Turing completeness', 'zh-cn:图灵完备; zh-tw:圖靈完備;'),
Item('Turing completeness', '图灵完备=>zh-cn:图灵完备; 图灵完备=>zh-sg:图灵完备; 图灵完备=>zh-my:图灵完全;'),
Item('Turing completeness', '圖靈完全=>zh-tw:圖靈完備; 圖靈完全=>zh-hk:圖靈完備; 圖靈完全=>zh-mo:圖靈完備;'),
Item('two-dimensional code', 'zh-cn:二维码; zh-tw:二維條碼;'),
Item('two-dimensional code', '二维条码=>zh-cn:二维码; 二维条码=>zh-sg:二维码; 二维条码=>zh-my:二维码;'),
Item('two-dimensional code', '二維碼=>zh-tw:二維條碼; 二維碼=>zh-hk:二維條碼; 二維碼=>zh-mo:二維條碼;'),
Item('two\'s complement', 'zh-cn:补码; zh-tw:二補數; zh-hk:二補碼;'),
Item('two\'s complement', '二进制补码=>zh-tw:二補數; 二进制补码=>zh-hk:二補碼; 二进制补码=>zh-mo:二補碼;'),
Item('two\'s-complement integer', '补码整数=>zh-tw:二補數;'),
Item('type', '型別=>zh-cn:类型; 型別=>zh-sg:类型; 型別=>zh-my:类型;'),
Item('type', '型態=>zh-cn:类型; 型態=>zh-sg:类型; 型態=>zh-my:类型;'),
Item('type checking', 'zh-cn:类型检查; zh-tw:型別檢查;'),
Item('type system', 'zh-cn:类型系统; zh-tw:型別系統;'),
{ type = 'text', text = [[
== U ==
]] },
Item('Ultrabook', 'zh-cn:超极本; zh-tw:超極致筆電; zh-hk:Ultrabook;'),
Item('Ultrabook', '超级本=>zh-tw:超極致筆電; 超级本=>zh-hk:Ultrabook; 超级本=>zh-mo:Ultrabook;'),
Item('unary function', 'zh-cn:单参函数; zh-tw:一元函式;'),
Item('unary function', '一元函數=>zh-cn:单参函数; 一元函數=>zh-tw:一元函式;'),
Item('underflow', '欠位=>zh-cn:下溢; 欠位=>zh-my:下溢; 欠位=>zh-sg:下溢;'),
Item('underline', 'zh-cn:下划线; zh-tw:底線;'),
Item('undo', 'zh-cn:撤销; zh-tw:復原;'),
Item('undo', '撤銷=>zh-tw:復原; 撤銷=>zh-hk:復原; 撤銷=>zh-mo:復原;'),
Item('undo', '撤消=>zh-tw:復原; 撤消=>zh-hk:復原; 撤消=>zh-mo:復原;'),
-- Item('update', '升级=>zh-tw:更新; 升级=>zh-hk:更新; 升级=>zh-mo:更新;'), 容易過度轉換
-- Item('update', '升級=>zh-tw:更新; 升級=>zh-hk:更新; 升級=>zh-mo:更新;'), 容易過度轉換
Item('unified shader model', 'zh-cn:统一渲染架构; zh-tw:統一著色器架構;'),
Item('uninstall', 'zh-cn:卸载; zh-tw:解除安裝;'),
Item('uninstall', '卸載=>zh-tw:解除安裝; 卸載=>zh-hk:解除安裝; 卸載=>zh-mo:解除安裝;'),
Item('Universal Serial Bus', 'zh-cn:通用串行总线; zh-tw:通用序列匯流排;'),
Item('Universal Serial Bus', '通用串列匯流排=>zh-cn:通用序列总线; 通用串列匯流排=>zh-sg:通用串行总线; 通用串列匯流排=>zh-my:通用串行总线;'),
Item('Universal Serial Bus', '通用串行總線=>zh-tw:通用序列匯流排; 通用串行總線=>zh-hk:通用序列匯流排; 通用串行總線=>zh-mo:通用序列匯流排;'),
Item('upload', 'zh-cn:上传;zh-tw:上傳;zh-hk:上載;'),
Item('upload', '上载=>zh-tw:上傳;'),
Item('UPS', 'zh-cn:电源保护; zh-tw:不斷電系統;'),
Item('URL shortening', 'zh-cn:缩略网址; zh-tw:縮網址;'),
Item('URL shortening', '縮略網址 => zh-tw:縮網址;'),
Item('USB flash drive', 'zh-cn:U盘; zh-tw:USB隨身碟; zh-hk:USB手指;'),
Item('USB flash drive', '闪存盘=>zh-tw:隨身碟; 闪存盘=>zh-hk:USB手指; 闪存盘=>zh-mo:USB手指;'),
Item('USB flash drive', '优盘=>zh-tw:隨身碟; 优盘=>zh-hk:USB手指; 优盘=>zh-mo:USB手指;'),
Item('USB flash drive', '隨身碟=>zh-cn:U盘; 隨身碟=>zh-sg:U盘; 隨身碟=>zh-my:U盘; 隨身碟=>zh-hk:USB手指; 隨身碟=>zh-mo:USB手指;'),
Item('user', 'zh-cn:用户;zh-sg:用户;zh-my:用户;zh-hk:用戶;zh-mo:用戶;zh-tw:使用者;'),
Item('user-generated content/user-created content', 'zh-hans:用户生成内容; zh-hant:用戶生成內容; zh-tw:使用者供應內容;'),
Item('user group', '使用者群=>zh-cn:用户组;使用者群=>zh-sg:用户组;使用者群=>zh-my:用户组;使用者群=>zh-hk:用戶組;使用者群=>zh-mo:用戶組;'),
Item('user group', 'zh-tw:使用者群組;zh-cn:用户组;zh-sg:用户组;zh-my:用户组;zh-hk:用戶組;zh-mo:用戶組;'),
Item('user interface', 'zh-cn:用户界面; zh-tw:使用者介面; zh-hk:用戶介面;'),
Item('user interface', '用户介面=>zh-cn:用户界面; 用户介面=>zh-sg:用户界面; 用户介面=>zh-my:用户界面;'),
Item('user interface', 'zh-cn:人机界面; zh-tw:人機介面;'),
Item('user page', 'zh-cn:用户页; zh-tw:使用者頁面; zh-hk:用戶頁;'),
Item('user page', '用戶頁面=>zh-cn:用户页; 用戶頁面=>zh-sg:用户页; 用戶頁面=>zh-my:用户页;'),
Item('userbox', 'zh-cn:用户框; zh-tw:使用者方塊; zh-hk:用戶框;'),
Item('username', 'zh-cn:用户名; zh-tw:使用者名稱; zh-hk:用戶名;'),
Item('username', '用戶名稱=>zh-cn:用户名; 用戶名稱=>zh-sg:用户名; 用戶名稱=>zh-my:用户名;'),
{ type = 'text', text = [[
== V ==
]] },
Item('variable', 'zh-cn:变量; zh-tw:變數;'),
Item('variable', '变数=>zh-cn:变量; 变数=>zh-sg:变量; 变数=>zh-my:变量;'),
Item('variable', '變量=>zh-tw:變數; 變量=>zh-hk:變數; 變量=>zh-mo:變數;'),
Item('variable bitrate', 'zh-cn:可变码率; zh-tw:變動位元速率; zh-hk:動態編碼率;'),
Item('vector', '矢量=>zh-tw:向量; 矢量=>zh-hk:向量; 矢量=>zh-mo:向量;'),
Item('vector graphics', 'zh-cn:矢量图形; zh-tw:向量圖形;'),
Item('VGA connector', 'zh-cn:视频接口; zh-tw:視訊連接頭; zh-hk:影像端子;'),
Item('video card', 'zh-cn:显卡; zh-tw:顯示卡;'),
Item('video card', '显示卡=>zh-cn:显卡; 显示卡=>zh-sg:显卡; 显示卡=>zh-my:显卡;'),
Item('video card', '顯卡=>zh-tw:顯示卡; 顯卡=>zh-hk:顯示卡; 顯卡=>zh-mo:顯示卡;'),
Item('video conference', 'zh-cn:视频会议; zh-tw:視訊會議; zh-hk:視像會議;'),
Item('video document', 'zh-cn:视频文档; zh-tw:視訊檔案;'),
Item('video file', 'zh-cn:视频文件; zh-tw:視訊檔; zh-hk:影片檔;'),
Item('video file', 'zh-cn:视频档; zh-tw:視訊檔; zh-hk:影片檔;'),
Item('video game', 'zh-hans:视频游戏; zh-hant:電動遊戲;'),
Item('video input', 'zh-cn:视频输入; zh-tw:視訊輸入; zh-hk:視頻輸入;'),
Item('video memory', 'zh-cn:显存; zh-tw:視訊記憶體; zh-hk:影像記憶體;'),
Item('video output', 'zh-cn:视频输出; zh-tw:視訊輸出; zh-hk:影像輸出;'),
Item('video processor', 'zh-cn:视频处理器; zh-tw:影像處理器;'),
Item('video streaming', 'zh-cn:影音流; zh-tw:影音串流;'),
Item('video track', 'zh-cn:视频轨; zh-tw:視訊軌; zh-hk:視頻軌;'),
Item('videotape', 'zh-cn:录像带; zh-tw:錄影帶;'),
Item('videotape', '录相带=>zh-tw:錄影帶; 录相带=>zh-hk:錄影帶; 录相带=>zh-mo:錄影帶;'),
Item('view', 'zh-cn:查看; zh-tw:檢視;'),
Item('virtual function', 'zh-cn:虚函数; zh-tw:虛擬函式;'),
Item('virtual function', '虛擬函數=>zh-cn:虚函数; 虛擬函數=>zh-tw:虛擬函式;'),
Item('virtual machine', 'zh-cn:虚拟机; zh-tw:虛擬機器;'),
Item('virtual memory', 'zh-cn:虚拟内存; zh-tw:虛擬記憶體;'),
Item('Virtual Private Network', 'zh-cn:虚拟专用网; zh-tw:虛擬私人網路;'),
Item('virtual reality', 'zh-cn:虚拟现实; zh-sg:虚拟实境; zh-my:虚拟实境; zh-tw:虛擬實境;'),
Item('virtual reality', 'zh:虛擬現實; zh-cn:虚拟现实; zh-sg:虚拟实境; zh-my:虚拟实境; zh-tw:虛擬實境;'),
Item('visit', '造訪=>zh-cn:访问; 造訪=>zh-sg:访问; 造訪=>zh-my:访问;'),
Item('visit link', '造訪連結=>zh-cn:访问链接; 造訪連結=>zh-tw:造訪連結;'),
Item('visit link', '访问链接=>zh-cn:访问链接; 访问链接=>zh-tw:造訪連結;'),
Item('visit webpage', '造訪網頁=>zh-cn:访问网页; 造訪網頁=>zh-tw:造訪網頁;'),
Item('visit webpage', '访问网页=>zh-cn:访问网页; 访问网页=>zh-tw:造訪網頁;'),
Item('visit website', '造訪網站=>zh-cn:访问网站; 造訪網站=>zh-tw:造訪網站;'),
Item('visit website', '访问网站=>zh-cn:访问网站; 访问网站=>zh-tw:造訪網站;'),
Item('visual', 'zh-cn:可视化; zh-tw:視覺化;'),
Item('volatile (memory)', 'zh-cn:易失性; zh-tw:揮發性;'),
Item('volume', '磁碟區=>zh-cn:卷; 磁碟區=>zh-sg:卷; 磁碟區=>zh-my:卷;'),
Item('Logical volume management', 'zh-cn:逻辑卷管理; zh-tw:邏輯捲軸管理;'),
Item('von Neumann', 'zh-hant:馮諾依曼; zh-hans:冯诺伊曼; zh-tw:馮諾伊曼;zh-cn:冯诺依曼;zh-hk:馮紐曼;'),
{ type = 'text', text = [[
== W ==
]] },
Item('wallpaper', 'zh-cn:壁纸; zh-tw:桌布;'),
Item('watermark', 'zh-cn:水印; zh-tw:浮水印;'),
Item('Watson', 'zh-cn:沃森; zh-tw:華生;'),
Item('weak typing', 'zh-cn:弱类型; zh-tw:弱型別;'),
Item('web animation', 'zh-cn:网络动画; zh-tw:網路動畫; zh-hk:網絡動畫;'),
Item('webcache', 'zh-cn:网页快照; zh-tw:頁面快取檔;'),
Item('webcam', 'zh-cn:摄像头; zh-tw:網路攝影機; zh-hk:網絡攝影機;'),
Item('webcomics', 'zh-cn:网络漫画; zh-tw:網路漫畫; zh-hk:網絡漫畫;'),
Item('Wide Area Network', 'zh-cn:广域网; zh-tw:廣域網路;'),
Item('wildcard character', 'zh-cn:通配符; zh-sg:万用字元; zh-tw:萬用字元;'),
-- Item('window', 'zh-cn:窗口; zh-tw:視窗;'), Microsoft Windows操作系统稱作視窗
Item('window manager', 'zh-cn:窗口管理器; zh-tw:視窗管理員;'),
Item('Western Digital', 'zh-cn:西部数据; zh-tw:威騰電子;'),
Item('wide screen', 'zh-cn:宽屏;zh-tw:寬螢幕;zh-hk:闊螢幕;'),
Item('wide screen', '宽面屏=>zh-tw:寬螢幕;宽面屏=>zh-hk:闊螢幕;宽面屏=>zh-mo:闊螢幕;'),
Item('wide screen', '寬面屏=>zh-tw:寬螢幕;寬面屏=>zh-hk:闊螢幕;寬面屏=>zh-mo:闊螢幕;'),
Item('Windows Explorer', 'zh-cn:资源管理器; zh-tw:檔案總管;'),
Item('wizard', 'zh-cn:向导; zh-tw:精靈;'),
Item('word process', 'zh-cn:文字处理; zh-tw:文書處理;'),
Item('word processor', 'zh-cn:文字处理器; zh-tw:文書處理器;'),
Item('workgroup', 'zh-cn:工作组; zh-tw:工作群組;'),
Item('World Wide Web', 'zh-cn:万维网; zh-tw:全球資訊網; zh-hk:萬維網;'),
Item('World Wide Web Consortium', 'zh-cn:万维网联盟; zh-tw:全球資訊網協會; zh-hk:萬維網聯盟;'),
Item('write-only', 'zh-cn:只写; zh-tw:唯寫;'),
Item('write-only memory', 'zh-cn:只写存储器; zh-tw:唯寫記憶體;'),
Item('write protection', 'zh-cn:写保护; zh-tw:防寫;'),
Item('Wind River', 'zh-cn:风河; zh-tw:溫瑞爾;'),
{ type = 'text', text = [[
== X ==
]] },
Item('Xerox', 'zh-cn:施乐; zh-tw:全錄; zh-hk:施樂;'),
Item('X window system', 'zh-cn:X窗口系统; zh-tw:X視窗系統; zh-hk:X Window系統;'),
Item('X window system', 'X视窗系统=>zh-cn:X窗口系统; X视窗系统=>zh-sg:X窗口系统; X视窗系统=>zh-my:X窗口系统;'),
Item('X window system', 'X Window系统=>zh-cn:X窗口系统; X Window系统=>zh-sg:X窗口系统; X Window系统=>zh-my:X窗口系统;'),
{ type = 'text', text = [[
== Y ==
]] },
Item('Yottabyte', 'zh-hans:尧字节; zh-hant:佑位元組;'),
Item('y2k', 'zh-hans:千年虫; zh-hk:千年蟲; zh-tw:千禧蟲;'),
{ type = 'text', text = [[
== Z ==
]] },
Item('Zettabyte', 'zh-hans:泽字节; zh-hant:皆位元組;'),
Item('Zuckerberg', 'zh-cn:扎克伯格; zh-tw:祖克柏; zh-hk:朱克伯格;'),
{ type = 'text', text = [[
== 其他 ==
]] },
Item('3-D film', 'zh-hans:三维电影; zh-hant:3D電影;'),
Item('3D computer', 'zh-hans:三维计算机; zh-hant:3D電腦;'),
Item('3D computer graphics', 'zh-hans:三维计算机图形; zh-hant:3D電腦圖形;'),
Item(nil, 'zh-cn:浏览框; zh-tw:瀏覽域;'),
Item(nil, 'zh-cn:定位框; zh-tw:定位域;'),
-- Item(nil, 'zh-cn:电信; zh-tw:電信; zh-hk:電訊;'), 容易過度轉換。該詞有可能是某些電信公司官方名稱中的一部分,例如「電訊盈科」變成「電信盈科」,「中華電信」變成「中華電訊」。
Item(nil, 'zh-cn:电信商; zh-tw:電信商; zh-hk:電訊商;'),
Item(nil, 'zh-cn:电信公司; zh-tw:電信公司; zh-hk:電訊公司;'),
Item(nil, 'zh-cn:电信业; zh-tw:電信業; zh-hk:電訊業;'),
Item(nil, 'zh-cn:电信运营商; zh-tw:電信業者; zh-hk:電訊供應商;'),
Item(nil, 'zh-cn:电信服务; zh-tw:電信服務; zh-hk:電訊服務;'),
Item(nil, 'zh-cn:电信行业; zh-tw:電信行業; zh-hk:電訊行業;'),
-- 简中少用“撷”
Item(nil, '擷=>zh-cn:截; 擷=>zh-sg:截; 擷=>zh-my:截;'),
Item(nil, 'zh-cn:乔布斯; zh-tw:賈伯斯; zh-hk:喬布斯;'),
Item(nil, 'zh-cn:鲍尔默; zh-tw:巴爾默;'),
Item(nil, 'zh-cn:扒站; zh-tw:砍站;'),
{ type = 'text', text = [[
== 防止過度轉換 ==
]] },
-- 避免 字体->字型 的過度轉換
Item(nil, 'zh-hans:文字体系; zh-hant:文字體系;'),
Item(nil, 'zh-hans:汉字体系; zh-hant:漢字體系;'),
-- 避免 當機->死机 的過度轉換
Item('dead robot', 'zh-hans:当机器; zh-hant:當機器;'),
-- 避免 時脈->时钟频率 的过度转换
Item('clock rate', '時脈頻率=>zh-cn:时钟频率; 時脈頻率=>zh-sg:时钟频率; 時脈頻率=>zh-my:时钟频率;'),
Item('contacts', 'zh-hans:通讯录; zh-hant:通訊錄;'),
Item('emoji', 'zh-hans:绘文字; zh-hant:繪文字;'),
-- 避免 程式->程序 的过度转换
Item('equation', 'zh-hans:方程式; zh-hant:方程式;'),
-- 避免 資料->数据/數據 的過度轉換
Item('References', 'zh-hans:参考资料; zh-hant:參考資料;'),
Item(nil, 'zh-hans:电视频; zh-hant:電視頻;'),
Item(nil, 'zh-hans:电影片; zh-hant:電影片;'),
Item(nil, 'zh-hans:字符号; zh-hant:字符號;'),
-- 以下均为名從主人
Item('China Telecom', 'zh-hans:中国电信; zh-hant:中國電信;'),
Item('Chunghwa Telecom', 'zh-hans:中华电信; zh-hant:中華電信;'),
Item(nil, 'zh-hans:网民报告; zh-hant:網民報告;'), -- 泡泡網民報告
Item(nil, 'zh-hans:网络电视台; zh-hant:網絡電視台;'),
Item(nil, 'zh-hans:网路电视台; zh-hant:網路電視台;'),
Item(nil, 'zh-hans:网络广播电视台; zh-hant:網絡廣播電視台;'),
Item(nil, 'zh-hans:网络安全和信息化; zh-hant:網絡安全和信息化;'),
Item(nil, 'zh-hans:互联网信息办公室; zh-hant:互聯網信息辦公室;'),
Item('CAC', 'zh-hans:中共中央网络安全和信息化领导小组办公室; zh-hant:中共中央網絡安全和信息化領導小組辦公室;'),
Item('CNCERT', 'zh-hans:国家互联网应急中心; zh-hant:國家互聯網應急中心;'),
Item('CNCERT', 'zh-hans:互联网应急中心; zh-hant:互聯網應急中心;'),
Item('CNNIC', 'zh-hans:中国互联网络信息中心; zh-hant:中國互聯網絡信息中心;'),
Item('CNNIC', 'zh-hans:互联网络信息中心; zh-hant:互聯網絡信息中心;'),
Item('Industry and Information Technology', 'zh-hans:工业和信息化; zh-hant:工業和信息化;'), -- 中华人民共和国工业和信息化部
Item('National Administration of Surveying, Mapping and Geoinformation', 'zh-hans:国家测绘地理信息局; zh-hant:國家測繪地理信息局;'),
Item('Hudong Baike', 'zh-hans:互动百科; zh-hant:互動百科;'),
Item('World Internet Conference', 'zh-hans:世界互联网大会; zh-hant:世界互聯網大會;'),
Item('Alibaba Cloud', 'zh-hans:阿里云计算; zh-hant:阿里雲計算;'),
Item('Tencent Cloud', 'zh-hans:腾讯云计算; zh-hant:騰訊雲計算;'),
Item('Baidu Cloud', 'zh-hans:百度云计算; zh-hant:百度雲計算;'),
Item('Baidu Cloud', 'zh-hans:百度网盘; zh-hant:百度網盤;'),
Item('LeCloud', 'zh-hans:乐视云计算; zh-hant:樂視雲計算;'),
Item('ByteDance', 'zh-hans:字节跳动; zh-hant:字節跳動;'),
Item(nil, 'zh-hans:人渣文本; zh-hant:人渣文本;'),
Item(nil, 'zh-hans:资讯台; zh-hant:資訊台;'),
Item(nil, 'zh-hans:资讯频道; zh-hant:資訊頻道;'), -- 避免电视频道名称过度转换
-- 防止「共享」過度轉換
Item('Wikimedia Commons', 'zh-hans:维基共享资源; zh-hant:維基共享資源;'),
Item('shareware', 'zh-cn:共享软件; zh-tw:共享軟體;'),
-- 防止「數據」過度轉換
Item('Wikidata', 'zh-hans:维基数据; zh-hant:維基數據;'),
-- 以下均为防止“视频”过度转换
Item('Baidu Video', 'zh-hans:百度视频; zh-hant:百度視頻;'),
Item('Netease Video', 'zh-hans:网易视频; zh-hant:網易視頻;'),
Item('Sina Video', 'zh-hans:新浪视频; zh-hant:新浪視頻;'),
Item('Sohu Video', 'zh-hans:搜狐视频; zh-hant:搜狐視頻;'),
Item('Tencent Video', 'zh-hans:腾讯视频; zh-hant:騰訊視頻;'),
Item('Tik Tok', 'zh-hans:抖音短视频; zh-hant:抖音短視頻;'),
Item('Tudou Video', 'zh-hans:土豆视频; zh-hant:土豆視頻;'),
Item('Vigo Video', 'zh-hans:火山小视频; zh-hant:火山小視頻;'),
Item('Xigua Video', 'zh-hans:西瓜视频; zh-hant:西瓜視頻;'),
Item('Youku Video', 'zh-hans:优酷视频; zh-hant:優酷視頻;'),
-- 以下均为防止“博客”过度转换
Item('Netease Blog', 'zh-hans:网易博客; zh-hant:網易博客;'),
Item('Sina Blog', 'zh-hans:新浪博客; zh-hant:新浪博客;'),
Item('Sohu Blog', 'zh-hans:搜狐博客; zh-hant:搜狐博客;'),
Item('Tencent Blog', 'zh-hans:腾讯博客; zh-hant:騰訊博客;'),
Item('Williamlong', 'zh-hans:月光博客; zh-hant:月光博客;'),
Item('bookstw', 'zh-hans:博客来; zh-hant:博客來;'), -- 台灣的博客來網路書店
-- 以下均为防止“相册”过度转换
Item('Netease Album', 'zh-hans:网易相册; zh-hant:網易相冊;'),
Item('Baidu Album', 'zh-hans:百度相册; zh-hant:百度相冊;'),
-- 以下均为防止“搜索”过度转换
Item('360 Search', 'zh-hans:360搜索; zh-hant:360搜索;'),
Item('Baidu Search', 'zh-hans:百度搜索; zh-hant:百度搜索;'),
Item('Sogou Search', 'zh-hans:搜狗搜索; zh-hant:搜狗搜索;'),
Item(nil, 'zh-hans:360综合搜索; zh-hant:360綜合搜索;'),
-- 防止公司名稱過度轉換
Item('Alibaba.com Ltd.', 'zh-hans:阿里巴巴网络; zh-hant:阿里巴巴網絡;'),
Item('Alibaba.com Ltd.', 'zh-hans:谷翔信息技术; zh-hant:谷翔信息技術;'),
Item('Sumavision', 'zh-hans:数码视讯; zh-hant:數碼視訊;'), -- 中国大陆的一家CA供应商
Item('Smartone', 'zh-hans:数码通; zh-hant:數碼通;'), -- 香港通信公司
Item('MODA', 'zh-hant:數位發展部; zh-hans:数位发展部;'), -- [[中華民國數位發展部]]
Item('MODA', 'zh-hant:數位部; zh-hans:数位部;'),
-- 避免 社区->社群 的過度轉換
Item(nil, 'zh-hans:草榴社区; zh-hant:草榴社區;'),
-- 避免 移动版->行動版/流動版 的過度轉換
Item(nil, 'zh-hans:移动版面; zh-hant:移動版面;'),
Item(nil, 'zh-hans:移动版块; zh-hant:移動版塊;'),
-- 避免 智能->智慧/智慧型 的過度轉換
Item(nil, 'zh-hans:智能ABC; zh-hant:智能ABC;'),
Item(nil, 'zh-hans:智慧城市; zh-hant:智慧城市;'),
-- 避免 命令列->命令行 的過度轉換
Item(nil, 'zh-hans:命令列表; zh-hant:命令列表;'),
-- 避免 支持->支援 的過度轉換
Item('support vector', 'zh-hans:支持向量; zh-hant:支持向量;'),
Item('supporter', 'zh-hans:支持者; zh-hant:支持者;'),
Item('I support', 'zh-hans:我支持; zh-hant:我支持;'),
Item('support me', 'zh-hans:支持我; zh-hant:支持我;'),
Item('support he', 'zh-hans:他支持; zh-hant:他支持;'),
Item('support he', 'zh-hans:支持他; zh-hant:支持他;'),
Item('support she', 'zh-hans:她支持; zh-hant:她支持;'),
Item('support she', 'zh-hans:支持她; zh-hant:支持她;'),
-- 避免 最优->最佳 的過度轉換
Item(nil, 'zh-hans:最优秀; zh-hant:最優秀;'),
Item(nil, 'zh-hans:最优美; zh-hant:最優美;'),
Item(nil, 'zh-hans:最优质; zh-hant:最優質;'),
Item(nil, 'zh-hans:最优先; zh-hant:最優先;'),
-- 避免 导出->匯出 的過度轉換
Item(nil, 'zh-hans:推导; zh-hant:推導;'),
-- 避免 子类->子類別 的過度轉換
Item(nil, '子类别=>zh-tw:子類別; 子类别=>zh-hk:子類別; 子类别=>zh-mo:子類別;'),
Item(nil, 'zh-hans:子类型; zh-hant:子類型;'),
-- 避免 C++类->C++類別 的過度轉換
Item(nil, 'zh-hans:C++类似; zh-hant:C++類似;'),
Item(nil, 'zh-hans:C++类型; zh-hant:C++類型;'),
-- 避免 C++的类->C++的類別 的過度轉換
Item(nil, 'zh-hans:C++的类型; zh-hant:C++的類型;'),
-- 避免 Java类->Java類別 的過度轉換
Item(nil, 'zh-hans:Java类似; zh-hant:Java類似;'),
Item(nil, 'zh-hans:Java类型; zh-hant:Java類型;'),
-- 避免 Java的类->Java的類別 的過度轉換
Item(nil, 'zh-hans:Java的类型; zh-hant:Java的類型;'),
-- 避免 复杂度类->複雜度類別 的過度轉換
Item(nil, 'zh-hans:复杂度类似; zh-hant:複雜度類似;'),
-- 避免 基于类->類別基礎 的過度轉換
Item(nil, 'zh-hans:基于类似; zh-hant:基於類似;'),
Item(nil, 'zh-hans:基于类型; zh-hant:基於類型;'),
-- 避免 布尔->布林 的過度轉換
Item(nil, 'zh-hans:·布尔; zh-hant:·布爾;'),
-- 避免 圖學->图形学 的過度轉換
Item(nil, 'zh-hans:地图学; zh-hant:地圖學;'),
Item(nil, 'zh-hans:试图学; zh-hant:試圖學;'),
Item(nil, 'zh-hans:企图学; zh-hant:企圖學;'),
Item(nil, 'zh-hans:电图学; zh-hant:電圖學;'),
-- 避免 執行->运行 的過度轉換
Item('executable', 'zh-hans:可执行; zh-hant:可執行;'),
Item('executor', 'zh-hans:执行者; zh-hant:執行者;'),
-- 避免 高亮->突顯 的過度轉換
Item(nil, 'zh-hans:高亮度; zh-hant:高亮度;'),
-- 避免 访问->存取 的過度轉換
Item(nil, 'zh-hans:访问学者; zh-hant:訪問學者;'),
-- 避免 存取->访问 的過度轉換
Item('random-access', 'zh-hans:随机存取; zh-hant:隨機存取;'),
-- 避免 代码/代碼->程式碼 的過度轉換
Item(nil, '程序代码=>zh-tw:程式碼; 程序代码=>zh-hk:程式碼; 程序代码=>zh-mo:程式碼;'),
Item(nil, '程序代碼=>zh-tw:程式碼; 程序代碼=>zh-hk:程式碼; 程序代碼=>zh-mo:程式碼;'),
Item(nil, '程式代码=>zh-tw:程式碼; 程式代码=>zh-hk:程式碼; 程式代码=>zh-mo:程式碼;'),
Item(nil, '程式代碼=>zh-tw:程式碼; 程式代碼=>zh-hk:程式碼; 程式代碼=>zh-mo:程式碼;'),
Item(nil, 'zh-hans:类型代码; zh-hant:類型代碼;'),
-- 避免 码率/碼率->位元速率 的過度轉換
Item(nil, 'zh-hans:误码率; zh-hant:誤碼率;'),
Item('rate of coincident code', 'zh-hans:重码率;zh-hant:重碼率;'),
-- 避免 交互->互動 的過度轉換
Item(nil, '交互資訊=>zh-tw:交互資訊; 交互資訊=>zh-hk:交互資訊; 交互資訊=>zh-mo:交互資訊;'),
-- 避免 程序->程式 的過度轉換
Item(nil, '預存程序=>zh-tw:預存程序; 預存程序=>zh-hk:預存程序; 預存程序=>zh-mo:預存程序;'),
-- 避免 復原->撤销 的過度轉換
Item(nil, 'zh-hans:回复原; zh-hant:回復原;'),
Item(nil, 'zh-hans:恢复原; zh-hant:恢復原;'),
-- 避免 模拟/模擬->類比 的過度轉換
Item('analogizer', 'zh-hans:模拟器; zh-hant:模擬器;'),
-- 避免 檔案->文件 的過度轉換
Item('archives', 'zh-hans:档案馆; zh-hant:檔案館;'),
Item('archives', 'zh-hans:档案室; zh-hant:檔案室;'),
-- 避免 字符->字元 的過度轉換
Item('Hong Kong Supplementary Character Set', 'zh-hans:香港增补字符集; zh-hant:香港增補字符集;'),
Item('Macao Supplementary Character Set', 'zh-hans:澳门增补字符集; zh-hant:澳門增補字符集;'),
-- 避免 資訊->信息 的過度轉換
Item('Macao Information System Character Set', 'zh-hans:澳门资讯系统字集; zh-hant:澳門資訊系統字集;'),
-- 避免 数据包->封包 的過度轉換
Item(nil, 'zh-cn:数据包括; zh-tw:資料包括; zh-hk:數據包括;'),
Item(nil, 'zh-cn:数据包含; zh-tw:資料包含; zh-hk:數據包含;'),
-- 避免 比特->位元 的過度轉換
Item('bitcent', 'zh-hans:比特分; zh-hant:比特分;'),
Item('bitcoin', 'zh-hans:比特币; zh-hant:比特幣;'),
Item('BitComet', 'zh-hans:比特彗星; zh-hant:比特彗星;'),
Item('BitSpirit', 'zh-hans:比特精灵; zh-hant:比特精靈;'),
Item('micro-bitcoin', 'zh-hans:微比特; zh-hant:微比特;'),
Item('milli-bitcoin', 'zh-hans:毫比特; zh-hant:毫比特;'),
Item('function library', 'zh-cn:函数库; zh-tw:函式庫;'),
Item('functional', 'zh-hans:函数式; zh-hant:函數式;'), -- 避免 函数/函數->函式 的過度轉換
Item('Office Suite', 'zh-hans:办公室套件; zh-hant:辦公室套件;'), -- 避免 套件->包 的過度轉換
Item('PPTV', 'zh-hans:PP视频; zh-hant:PP視頻;'), -- 避免 PP视频->PP影片 的過度轉換
Item('real mode', '真实模式=>zh-tw:真實模式; 真实模式=>zh-hk:真實模式; 真实模式=>zh-mo:真實模式;'), -- 避免 实模式->真實模式 的過度轉換
Item('rolling update', 'zh-hans:滚动更新; zh-hant:滾動更新;'), -- 避免 滚动->捲動 的過度轉換
Item('script kiddie', 'zh-hans:脚本小子; zh-hant:腳本小子;'), -- 避免 脚本->指令碼 的過度轉換
Item('tablet computer', 'zh-hans:平板电脑; zh-hant:平板電腦;'), -- 避免 电脑/電腦->计算机 的過度轉換
-- 避免 佈景->布景 的過度轉換
Item('theme', '布景主题=>zh-tw:佈景主題; 佈景主題=>zh-tw:佈景主題;'),
-- 避免 字型->字体 的過度轉換
Item('wubi', 'zh-hans:五笔字型; zh-hant:五筆字型;'),
-- 避免 运算符->運算子 的過度轉換
Item('operator', 'zh-hans:运算符号; zh-hant:運算符號;'),
-- 避免 代码/代碼->程式碼 的過度轉換
Item('code list', 'zh-hans:代码表; zh-hant:代碼表;'),
-- 避免 国家安全局->國家安全域 的過度轉換
Item('NSB', '国家安全局=>zh-tw:國家安全局; 國家安全局=>zh-tw:國家安全局;'),
-- 避免 完全屏蔽->完全螢幕蔽 的過度轉換
Item('block', 'zh-hans:完全屏蔽; zh-hant:完全屏蔽;'),
-- 避免 中文介面->中文接口 的過度轉換
Item('XXX language interface', 'zh-cn:文界面; zh-tw:文介面; zh-hk:文介面;'),
Item('China Computer Federation', 'zh-hans:中国计算机学会; zh-hant:中國計算機學會;'),
},
}
a604cd2a89f68174ec9a0f5c9462fc1099f12bef
Module:CGroup/MediaWiki
828
134
269
268
2024-08-02T10:54:57Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- 用法: Item('原文', '轉換規則')
local Item = require('Module:CGroup/core').Item;
return {
name = 'MediaWiki',
description = 'MediaWiki',
content = {
{ type = 'text', text = [=[
{{NoteTA/MediaWiki}}
本转换组为MediaWiki及中文维基百科专有用语。
由于中文维基百科部分统一用语与常见IT术语不同,可视情况与[[Module:CGroup/IT]]配合使用来抵消[[Module:CGroup/IT]]带来的过度转换。
本转换组只应用于Wikipedia、Help、Template等命名空间或与维基百科相关的条目,请勿用于其他主命名空间条目内。
如無特別需求請直接使用{{tlx|NoteTA/MediaWiki}}
== 專有名稱 ==
]=] },
Item('account', 'zh-cn:账号; zh-tw:帳號;'),
Item('account', '账户=>zh-cn:账号; 账户=>zh-tw:帳號;'),
Item('account', '賬戶=>zh-cn:账号; 賬戶=>zh-tw:帳號;'),
Item('account', '賬號=>zh-cn:账号; 賬號=>zh-tw:帳號;'),
Item('account', '帐户=>zh-cn:账号; 帐户=>zh-tw:帳號;'),
Item('account', '帳戶=>zh-cn:账号;'),
Item('account', '帐号=>zh-cn:账号; 帐号=>zh-tw:帳號;'),
Item('account creator', 'zh-cn:大量账号创建者; zh-tw:大量帳號建立者; zh-hk:大量帳號建立者;'),
Item('advanced', 'zh-cn:高级; zh-tw:進階;'),
Item('authority control', 'zh-cn:规范控制; zh-tw:權威控制;'),
Item('block', 'zh-cn:封禁; zh-tw:封鎖; zh-hk:封鎖;'),
Item('change', 'zh-cn:更改; zh-tw:變更;'),
Item('character', 'zh-cn:字符; zh-tw:字元;'),
Item('copyright', 'zh-cn:著作权; zh-tw:著作權; zh-hk:版權; zh-mo:著作權;'),
Item('copyright', '版权=>zh-tw:著作權; 版权=>zh-mo:著作權;'),
Item('copyright information', '版权信息=>zh-cn:著作权信息; 版权信息=>zh-sg:著作权信息; 版权信息=>zh-my:著作权信息; 版权信息=>zh-tw:著作權資訊; 版权信息=>zh-mo:著作權資訊;'),
Item('create', 'zh-cn:创建; zh-tw:建立;'),
Item('create', '創建=>zh-tw:建立; 創建=>zh-hk:建立; 創建=>zh-mo:建立;'),
Item('custom', 'zh-cn:自定义; zh-tw:自訂;'),
Item('custom', '自定義=>zh-hk:自訂; 自定義=>zh-tw:自訂;'),
Item('custom', '自定=>zh-hk:自訂; 自定=>zh-tw:自訂;'),
Item('default', 'zh-cn:默认; zh-tw:預設;'),
Item('default', '默認=>zh-tw:預設;'),
Item('file', 'zh-cn:文件; zh-tw:檔案;'),
Item('file', '档案=>zh-cn:文件; 档案=>zh-sg:文件; 档案=>zh-my:文件;'),
Item('file name', 'zh-cn:文件名; zh-tw:檔案名稱;'),
Item('flood', 'zh-hans:机器用户; zh-tw:機器使用者; zh-hk:機械用戶;'),
Item('footnote', 'zh-cn:脚注; zh-tw:註腳;'),
Item('Help:', 'zh-cn:帮助:; zh-tw:說明:;'),
Item('Help talk:', 'zh-cn:帮助讨论:; zh-tw:說明討論:;'),
Item('info (information)', 'zh-cn:信息; zh-tw:資訊;'),
Item('interface', 'zh-hans:界面; zh-hant:介面;'),
Item('interface administrators', 'zh-cn:界面管理员; zh-tw:介面管理員;'),
Item('IP block exemption', 'zh-cn:IP封禁豁免; zh-tw:IP封鎖豁免;'),
Item('IP block exemption', 'IP封禁例外=>zh-hans:IP封禁豁免; IP封禁例外=>zh-hant:IP封鎖豁免;'),
Item('IP block exemption', 'IP封鎖例外=>zh-hans:IP封禁豁免; IP封禁例外=>zh-hant:IP封鎖豁免;'),
--[=[
抄自[[Module:CGroup/IT]]
因為現在要求不要沒事加上IT以防過度轉換
結果 链接/鏈接/連結 又不轉換了
]=]
Item('import', 'zh-cn:导入; zh-tw:匯入;'),
Item('import', '汇入=>zh-cn:导入; 汇入=>zh-sg:导入; 汇入=>zh-my:导入;'),
Item('import', '導入=>zh-tw:匯入; 導入=>zh-hk:匯入; 導入=>zh-mo:匯入;'),
Item('line breaker', 'zh-hans:换行符;zh-hant:換行字元;'),
Item('line breaker', 'zh:換行符;zh-hans:换行符;zh-hant:換行字元;'),
Item('line breaker', 'zh:换行字元;zh-hans:换行符;zh-hant:換行字元;'),
Item('link', 'zh-cn:链接; zh-tw:連結;'),
Item('link', '连结=>zh-cn:链接; 连结=>zh-sg:链接; 连结=>zh-my:链接;'),
Item('link', '鏈接=>zh-tw:連結; 鏈接=>zh-hk:連結; 鏈接=>zh-mo:連結;'),
Item('link', '鏈結=>zh-tw:連結; 鏈結=>zh-hk:連結; 鏈結=>zh-mo:連結;'),
Item('internal link', '内链=>zh-tw:內部連結; 内链=>zh-hk:內部連結; 内链=>zh-mo:內部連結;'),
Item('internal link', '內鏈=>zh-tw:內部連結; 內鏈=>zh-hk:內部連結; 內鏈=>zh-mo:內部連結;'),
Item('external link', '外链=>zh-tw:外部連結; 外链=>zh-hk:外部連結; 外链=>zh-mo:外部連結;'),
Item('external link', '外鏈=>zh-tw:外部連結; 外鏈=>zh-hk:外部連結; 外鏈=>zh-mo:外部連結;'),
Item('red link', '红链=>zh-tw:紅色連結; 红链=>zh-hk:紅色連結; 红链=>zh-mo:紅色連結;'),
Item('red link', '紅鏈=>zh-tw:紅色連結; 紅鏈=>zh-hk:紅色連結; 紅鏈=>zh-mo:紅色連結;'),
Item('green link', '绿链=>zh-tw:綠色連結; 绿链=>zh-hk:綠色連結; 绿链=>zh-mo:綠色連結;'),
Item('green link', '綠鏈=>zh-tw:綠色連結; 綠鏈=>zh-hk:綠色連結; 綠鏈=>zh-mo:綠色連結;'),
Item('blue link', '蓝链=>zh-tw:藍色連結; 蓝链=>zh-hk:藍色連結; 蓝链=>zh-mo:藍色連結;'),
Item('blue link', '藍鏈=>zh-tw:藍色連結; 藍鏈=>zh-hk:藍色連結; 藍鏈=>zh-mo:藍色連結;'),
Item('link (here)', 'zh-cn:链入; zh-tw:連入;'),
Item('link (here)', '鏈入=>zh-tw:連入;'),
-- end
Item('log details', 'zh-hans:日志详情; zh-hant:日誌明細;'),
Item('login', 'zh-hans:登录; zh-hant:登入;'),
Item('logout', 'zh-hant:登出; zh-hans:退出;'), -- 覆蓋[[Module_talk:CGroup/IT#編輯請求_2023-06-13]]
Item('logout', '退出登录 => zh-tw:登出; 退出登录 => zh-hk:登出; 退出登录 => zh-mo:登出; '), -- 你永遠想不到編者怎麼造成轉換錯誤
Item('module', 'zh-cn:模块; zh-tw:模組;'),
Item('module', '模组=>zh-cn:模块; 模组=>zh-sg:模块; 模组=>zh-my:模块;'),
Item('namespace', 'zh-hans:命名空间; zh-hant:命名空間;'),
Item('namespace', '名字空间=>zh-cn:命名空间; 名字空间=>zh-hk:命名空間; 名字空间=>zh-mo:命名空間; 名字空间=>zh-tw:命名空間; 名字空间=>zh-sg:命名空间; 名字空间=>zh-my:命名空间;'),
Item('namespace', '名字空間=>zh-cn:命名空间; 名字空間=>zh-hk:命名空間; 名字空間=>zh-mo:命名空間; 名字空間=>zh-tw:命名空間; 名字空間=>zh-sg:命名空间; 名字空間=>zh-my:命名空间;'),
Item('parser functions', 'zh-cn:解析器函数; zh-hk:解析器函數; zh-tw:解析器函數;'),
Item('preferences', 'zh-cn:参数设置; zh-tw:偏好設定; zh-hk:參數設置;'),
Item('project', 'zh-hans:项目; zh-hant:專案; zh-tw:專案;'),
--[=[
誤轉率過高,真的要用請用 项目 代替 項目 即可轉換
Item('project', '項目=>zh-tw:專案; 項目=>zh-hk:專案; 項目=>zh-mo:專案;'),
]=]--
Item('project', '专案=>zh-cn:项目; 专案=>zh-sg:项目; 专案=>zh-my:项目; 专案=>zh-tw:專案;'),
Item('project', '計劃=>zh-cn:项目; 計劃=>zh-sg:项目; 計劃=>zh-my:项目; 計劃=>zh-tw:專案; 計劃=>zh-hk:專案; 計劃=>zh-mo:專案;'),
Item('project page', 'zh-hans:项目页面; zh-hant:專案頁面; zh-tw:專案頁面;'),
Item('project page', '項目頁面=>zh-tw:計畫頁面; 項目頁面=>zh-hk:專案頁面; 項目=>zh-mo:專案頁面;'),
Item('recent change', 'zh-hans:最近更改; zh-hant:近期變更;'),
Item('redirect', 'zh-cn:重定向; zh-tw:重新導向;'),
Item('redirect page', 'zh-cn:重定向页; zh-tw:重新導向頁面;'),
Item('redirect page', '重定向页面=>zh-tw:重新導向頁面; 重定向页面=>zh-hk:重新導向頁面; 重定向页面=>zh-mo:重新導向頁面;'),
Item('report', 'zh-cn:举报; zh-tw:檢舉;'),
Item('sample', 'zh-cn:示例; zh-tw:範例;'),
Item('skin', '皮肤=>zh-tw:外觀; 皮肤=>zh-hk:外觀; 皮肤=>zh-mo:外觀;'),
Item('source code', 'zh-hans:原始码; zh-hant:原始碼; zh-cn:源代码;'),
Item('source code', '源代碼=>zh-hk:原始碼; 源代碼=>zh-mo:原始碼; 源代碼=>zh-tw:原始碼; 源代碼=>zh-sg:原始码; 源代碼=>zh-my:原始码;'),
Item('source code', '源码=>zh-hk:原始碼; 源码=>zh-mo:原始碼; 源码=>zh-tw:原始碼; 源码=>zh-sg:原始码; 源码=>zh-my:原始码;'),
Item('source code', '源碼=>zh-hk:原始碼; 源碼=>zh-mo:原始碼; 源碼=>zh-tw:原始碼; 源碼=>zh-sg:原始码; 源碼=>zh-my:原始码;'),
Item('string', 'zh-cn:字符串; zh-tw:字串;'),
Item('template data', 'zh-hans:模板数据; zh-hant:模板資料; zh-tw:模板資料;'),
Item('template documentation', 'zh-hans:模板文档; zh-hant:模板文件;'),
Item('through', 'zh-cn:通过; zh-tw:透過;'),
Item('undo', 'zh-cn:撤销; zh-tw:復原;'),
Item('undo', '撤消=>zh-tw:復原; 撤消=>zh-hk:復原; 撤消=>zh-mo:復原;'),
Item('user', 'zh-hans:用户; zh-hant:使用者; zh-tw:使用者; zh-hk:用戶;'), ---容易过度转换
Item('user group', 'zh-cn:用户组; zh-tw:使用者群組; zh-hk:用戶組;'),
Item('user page', 'zh-cn:用户页; zh-tw:使用者頁面; zh-hk:用戶頁;'),
Item('user page', '用户頁=>zh-tw:使用者頁面;'),
Item('user page', '用戶页=>zh-tw:使用者頁面;'),
Item('user page', '用户页面=>zh-tw:使用者頁面;'),
Item('user page', '使用者頁=>zh-tw:使用者頁面;'),
Item('user page', '使用者頁面=>zh-tw:使用者頁面;'),
Item('user right', '用户权限 => zh-tw:使用者權限;用戶權限 => zh-tw:使用者權限;'),
Item('user right', '用户权 => zh-tw:使用者權限;用戶權 => zh-tw:使用者權限;'),
Item('userbox', 'zh-cn:用户框; zh-tw:使用者方塊; zh-hk:用戶框;'),
Item('username', 'zh-hans:用户名; zh-hant:用戶名; zh-tw:使用者名稱;'),
Item('username', '用户名称=>zh-cn:用户名; 用户名称=>zh-my:用户名; 用户名称=>zh-sg:用户名; 用户名称=>zh-tw:使用者名稱;'),
Item('username', '用戶名稱=>zh-cn:用户名; 用戶名稱=>zh-my:用户名; 用戶名稱=>zh-sg:用户名; 用戶名稱=>zh-tw:使用者名稱;'),
Item('view', 'zh-cn:查看; zh-tw:檢視;'),
Item('visual', 'zh-cn:可视化; zh-tw:視覺化;'), -- VisualEditor
Item('watchlist', 'zh-cn:监视列表; zh-tw:監視清單;'),
{ type = 'text', text = [=[
== 避免過度轉換 ==
]=] },
--[=[
此區僅用來防止過度轉換,請按照過度轉換源提供的轉換方式(ex.zh-hans:xxx; zh-hant:xxx; 或 zh-cn:xxx; zh-tw:xxx;)加入,避免無法覆蓋
]=]--
Item('archives', 'zh-cn:档案馆; zh-tw:檔案館;'), -- 避免 档案馆->文件馆 的過度轉換
Item('archives', '档案馆=>zh-cn:档案馆; 档案馆=>zh-sg:档案馆; 档案馆=>zh-my:档案馆;'), -- 避免 档案馆->文件馆 的過度轉換
Item('administrator intervention against vandalism', 'zh-hans:当前的破坏; zh-hant:目前的破壞;'), -- 「当前=>目前」非過度轉換
Item('cite', 'zh-hans:引用; zh-hant:引用;'), -- 避免 引用->參照 的過度轉換
Item('commons', 'zh-hans:共享资源; zh-hant:共享資源;'), -- 避免 共享->共用 的過度轉換
Item('global', 'zh-cn:全域; zh-tw:全域;'),
Item('log', 'zh-hans:日志; zh-hant:日誌;'), -- 避免 日志->紀錄檔 的過度轉換
Item('log entry', 'zh-cn:日志项目; zh-tw:日誌項目;'), -- 避免 项目->專案/計畫/計劃 的過度轉換
Item(nil, 'zh-hans:主页面; zh-hant:主頁面;'), -- 避免 主頁->首頁 的過度轉換
Item('message', 'zh-hans:讯息; zh-hant:訊息;'), -- 避免 訊息->消息 的過度轉換
Item('native', 'zh-hans:本地的; zh-hant:本地的;'), -- 避免 本地的->原生的 的過度轉換
Item('object', 'zh-hans:对象; zh-hant:對象;'), -- 避免 对象->物件 的過度轉換
Item('perform', 'zh-hans:执行; zh-hant:執行;'), -- 避免 執行->运行 的過度轉換
Item('procedure', 'zh-hans:程序; zh-hant:程序;'), -- 避免 程序->程式 的過度轉換
Item('segment', 'zh-hans:区段; zh-hant:區段;'), -- 避免 區段->区块 的過度轉換
Item('sign', 'zh-hans:签名; zh-hant:簽名;'), -- 避免 签名->簽章 的過度轉換
Item('support', 'zh-hans:支持; zh-hant:支持;'), -- 避免 支持->支援 的過度轉換
Item('user namespace', '用户名字空間=>zh-hk:用戶命名空間; 用户名字空間=>zh-mo:用戶命名空間; 用户名字空間=>zh-tw:使用者命名空間;'), -- 避免 用户名->使用者名稱 的過度轉換
Item('user namespace', '用戶名字空间=>zh-hk:用戶命名空間; 用戶名字空间=>zh-mo:用戶命名空間; 用戶名字空间=>zh-tw:使用者命名空間;'), -- 避免 用戶名->使用者名稱 的過度轉換
Item('user namespace', '用戶名字空間=>zh-hk:用戶命名空間; 用戶名字空間=>zh-mo:用戶命名空間; 用戶名字空間=>zh-tw:使用者命名空間;'), -- 避免 用戶名->使用者名稱 的過度轉換
-- 註:“名字空間”是舊的簡體中文譯名,後來簡體中文譯名改為“命名空間”,與繁體用詞保持一致。參見[[维基百科:互助客栈/其他/存档/2021年10月#關於zh-hans/zh-Hans-CN中namespace的翻譯]]。舊的用法保留在轉換表中。
Item('community', 'zh-hans:社群; zh-hant:社群;'), -- 避免 社区->社群 的過度轉換
Item(nil, '授權=>zh-cn:授权; zh-tw:授權;'), -- 避免 授權->特許 的過度轉換
Item(nil, '特許=>zh-cn:授权; zh-tw:特許;'), -- 避免 授權->特許 的過度轉換
},
}
544bbe041f7983229cdd1111fe31a6be6b0bf162
Template:Documentation subpage
10
101
271
197
2024-08-02T10:54:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[那艺娜维基:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
a29fcace7b5ee767264d3f8874aa71d0eb6ec03d
Module:Lua banner
828
108
273
211
2024-08-02T10:54:59Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[那艺娜维基:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
dc0cc1f5c839b737e09cd1889b2121194b550c65
Module:Protection banner/config
828
111
275
217
2024-08-02T10:55:01Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[那艺娜维基:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[那艺娜维基:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[那艺娜维基:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[那艺娜维基:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[那艺娜维基:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[那艺娜维基:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[那艺娜维基:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[那艺娜维基:封禁方针|封禁]]或被'
.. '[[那艺娜维基:編輯禁制方針|編輯禁制]]用户的[[那艺娜维基:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[那艺娜维基:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[那艺娜维基:高風險模板|高風險模板]],'
.. '已被永久[[那艺娜维基:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]或'
.. '[[那艺娜维基:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏|破坏]]而被保护的页面',
text = '由于[[那艺娜维基:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[那艺娜维基:用户权限'
.. '级别#新用户|新用户]]或[[那艺娜维基:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[那艺娜维基:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[那艺娜维基:用户权限级别#新用户|新用户]] or'
.. ' [[那艺娜维基:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[那艺娜维基:Reviewing|reviewers]] or'
.. ' [[那艺娜维基:管理员|管理员]] are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[那艺娜维基:共识'
.. '|共识]]基础,您可以向'
.. '[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[那艺娜维基:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[那艺娜维基:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[那艺娜维基:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[那艺娜维基:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = '那艺娜维基:保護方針#全保护',
templateeditor = '那艺娜维基:保護方針#模板保护',
extendedconfirmed = '那艺娜维基:保護方針#延伸確認保護',
autoconfirmed = '那艺娜维基:保護方針#半保护'
},
move = {
default = '那艺娜维基:保護方針#移动保护'
},
autoreview = {
autoconfirmed = '那艺娜维基:保護方針#pc1',
reviewer = '那艺娜维基:保護方針#pc2'
},
upload = {
default = '那艺娜维基:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[那艺娜维基:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
7094c99bbb3daa4ca9c6e7979c5de465b77c2398
Module:Transclusion count
828
115
277
225
2024-08-02T10:55:02Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[那艺娜维基:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
c08ee42f72543653cc35e9f1ae778d67e049f7b4
Module:Transclusion count/data/I
828
135
279
278
2024-08-02T10:55:03Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
["ICounter"] = 9200,
["IDN"] = 4700,
["IMDb_name"] = 14000,
["IMDb_title"] = 16000,
["IND"] = 9800,
["IPA"] = 49000,
["IPA-fr"] = 38000,
["IPA/styles.css"] = 49000,
["IPA_audio_link"] = 8800,
["IPAc-en"] = 3200,
["IRL"] = 2300,
["IRN"] = 2800,
["ISBN"] = 12000,
["ISODate"] = 6400,
["ISO_3166_code"] = 100000,
["ISO_639_name"] = 396000,
["ISO_639_name_de"] = 23000,
["ISO_639_name_el"] = 2600,
["ISO_639_name_en"] = 244000,
["ISO_639_name_es"] = 16000,
["ISO_639_name_fr"] = 17000,
["ISO_639_name_hu"] = 2900,
["ISO_639_name_it"] = 3800,
["ISO_639_name_ja"] = 102000,
["ISO_639_name_ja-latn"] = 4700,
["ISO_639_name_ko"] = 23000,
["ISO_639_name_ko-hang"] = 4200,
["ISO_639_name_ko-hani"] = 3500,
["ISO_639_name_ko-latn"] = 4000,
["ISO_639_name_la"] = 80000,
["ISO_639_name_mn"] = 2200,
["ISO_639_name_nan"] = 3500,
["ISO_639_name_pinyin"] = 3200,
["ISO_639_name_pt"] = 8200,
["ISO_639_name_ru"] = 11000,
["ISO_639_name_th"] = 2100,
["ISO_639_name_uk"] = 2100,
["ISO_639_name_vi"] = 5900,
["ISO_639_name_vi-hani"] = 3600,
["ISO_639_name_yue"] = 2000,
["ISO_639_name_zh"] = 54000,
["ISR"] = 3100,
["ISSN_link"] = 2800,
["ITA"] = 15000,
["ITNtalk"] = 5500,
["ITNtalk/date"] = 5500,
["IUCN"] = 4100,
["Icon"] = 56000,
["If"] = 12000,
["IfFlow"] = 2000,
["IfIP"] = 4500,
["IfPNS"] = 666000,
["If_both"] = 5400,
["If_declined"] = 16000,
["If_empty"] = 603000,
["If_in_page"] = 676000,
["If_mobile"] = 64000,
["If_mobile/styles.css"] = 88000,
["If_pagename"] = 604000,
["If_preview"] = 48000,
["If_subst"] = 744000,
["If_then_show"] = 4300,
["IfdFileInfo"] = 3300,
["IfdLinkNext"] = 9200,
["IfdLinkToday"] = 3000,
["IfdLinkToday/auto"] = 2000,
["IfdUploader"] = 3300,
["Ifempty"] = 37000,
["Ifexist_not_redirect"] = 3100,
["Ifnumber"] = 27000,
["Ifsubst"] = 766000,
["Illinois-geo-stub"] = 4200,
["Image"] = 14000,
["Image_label"] = 3000,
["Image_label_begin"] = 2500,
["Image_other"] = 68000,
["Image_requested"] = 2100,
["Imbox"] = 68000,
["Imbox/style.css"] = 68000,
["Imdb_name"] = 4300,
["Imdb_title"] = 7100,
["Importance"] = 577000,
["Importance-col"] = 577000,
["Importance_mask"] = 647000,
["Importancecol"] = 577000,
["In_lang"] = 3400,
["Include-USGov"] = 5100,
["Increase"] = 6700,
["Indef"] = 12000,
["Indefblockeduser"] = 4000,
["Indiana-geo-stub"] = 3800,
["Infobox"] = 688000,
["Infobox3cols"] = 17000,
["Infobox_China_County"] = 3000,
["Infobox_China_railway_station"] = 6300,
["Infobox_Chinese/Footer"] = 5800,
["Infobox_Chinese/Header"] = 5800,
["Infobox_Chinese/Korean"] = 4000,
["Infobox_City"] = 3700,
["Infobox_Company"] = 6000,
["Infobox_EPW"] = 5900,
["Infobox_Film"] = 6800,
["Infobox_French_commune"] = 31000,
["Infobox_French_former_commune"] = 2400,
["Infobox_Indian_jurisdiction"] = 4500,
["Infobox_Italian_comune"] = 7600,
["Infobox_Korean_name"] = 3600,
["Infobox_Korean_name/categories"] = 3600,
["Infobox_Military_Conflict"] = 2900,
["Infobox_NBA_Player"] = 2200,
["Infobox_Officeholder"] = 6800,
["Infobox_PRCG"] = 3000,
["Infobox_Person"] = 3700,
["Infobox_Reservoir"] = 2100,
["Infobox_Roman_Catholic_diocese"] = 2900,
["Infobox_School"] = 3400,
["Infobox_Settlement"] = 8700,
["Infobox_Single"] = 2500,
["Infobox_Television"] = 4400,
["Infobox_VG"] = 5200,
["Infobox_Weapon"] = 2300,
["Infobox_airport"] = 2000,
["Infobox_album"] = 9600,
["Infobox_album/color"] = 13000,
["Infobox_album/link"] = 9600,
["Infobox_animanga/Collapsible"] = 6100,
["Infobox_animanga/CustomItem"] = 6900,
["Infobox_animanga/Footer"] = 6900,
["Infobox_animanga/Footerofja"] = 6700,
["Infobox_animanga/Head"] = 6900,
["Infobox_animanga/Header2"] = 6900,
["Infobox_animanga/Headerofja"] = 6800,
["Infobox_animanga/Image"] = 6600,
["Infobox_animanga/Item"] = 6900,
["Infobox_animanga/Manga"] = 4200,
["Infobox_animanga/TVAnime"] = 3200,
["Infobox_animanga/name"] = 2900,
["Infobox_award"] = 2100,
["Infobox_badminton_event"] = 2200,
["Infobox_badminton_player"] = 2600,
["Infobox_baseball_biography"] = 4300,
["Infobox_baseball_biography/style"] = 4300,
["Infobox_basketball_biography"] = 3900,
["Infobox_basketball_biography/style"] = 4000,
["Infobox_body_of_water"] = 3400,
["Infobox_book"] = 4300,
["Infobox_building"] = 5700,
["Infobox_bus_route"] = 2500,
["Infobox_company"] = 14000,
["Infobox_country"] = 2700,
["Infobox_country/formernext"] = 3200,
["Infobox_country/imagetable"] = 2400,
["Infobox_country/multirow"] = 4200,
["Infobox_country_at_games"] = 2400,
["Infobox_designation_list"] = 3900,
["Infobox_designation_list/entry"] = 3400,
["Infobox_diocese"] = 3200,
["Infobox_drug"] = 2100,
["Infobox_drug/chemical_formula"] = 2100,
["Infobox_drug/data_page_link"] = 2100,
["Infobox_drug/formatATC"] = 2100,
["Infobox_drug/formatChEBI"] = 2100,
["Infobox_drug/formatChEMBL"] = 2100,
["Infobox_drug/formatChemDBNIAID"] = 2100,
["Infobox_drug/formatChemSpider"] = 2100,
["Infobox_drug/formatCompTox"] = 2100,
["Infobox_drug/formatDrugBank"] = 2100,
["Infobox_drug/formatIUPHARBPS"] = 2100,
["Infobox_drug/formatJmol"] = 2100,
["Infobox_drug/formatKEGG"] = 2100,
["Infobox_drug/formatPubChemCID"] = 2100,
["Infobox_drug/formatPubChemSID"] = 2100,
["Infobox_drug/formatUNII"] = 2100,
["Infobox_drug/legal_status"] = 2100,
["Infobox_drug/licence"] = 2100,
["Infobox_drug/maintenance_categories"] = 2100,
["Infobox_drug/pregnancy_category"] = 2100,
["Infobox_drug/title"] = 2100,
["Infobox_entertainer"] = 2700,
["Infobox_film"] = 6700,
["Infobox_football_biography"] = 14000,
["Infobox_football_club"] = 3400,
["Infobox_former_subdivision"] = 2000,
["Infobox_historic_site"] = 3300,
["Infobox_lake"] = 3000,
["Infobox_language"] = 2300,
["Infobox_language/family-color"] = 2700,
["Infobox_language/linguistlist"] = 2300,
["Infobox_language/vitality"] = 2600,
["Infobox_language/vitality-short"] = 2600,
["Infobox_mapframe"] = 98000,
["Infobox_medal_templates"] = 31000,
["Infobox_military_conflict"] = 5700,
["Infobox_military_person"] = 3300,
["Infobox_military_unit"] = 2800,
["Infobox_mountain"] = 2200,
["Infobox_museum"] = 2000,
["Infobox_musical_artist"] = 3300,
["Infobox_musical_artist/hCard_class"] = 12000,
["Infobox_officeholder"] = 27000,
["Infobox_officeholder/office"] = 30000,
["Infobox_organization"] = 3500,
["Infobox_person"] = 33000,
["Infobox_person/Wikidata"] = 29000,
["Infobox_person/core"] = 33000,
["Infobox_person/height"] = 20000,
["Infobox_person/height/locate"] = 20000,
["Infobox_person/height/switch"] = 20000,
["Infobox_person/weight"] = 5200,
["Infobox_person/weight/locate"] = 5200,
["Infobox_person/weight/switch"] = 5200,
["Infobox_planet"] = 13000,
["Infobox_political_party"] = 2800,
["Infobox_rail_system-route"] = 3600,
["Infobox_religious_building"] = 4500,
["Infobox_religious_building/color"] = 4600,
["Infobox_religious_building/count"] = 4500,
["Infobox_reservoir"] = 2100,
["Infobox_river"] = 3100,
["Infobox_river/source"] = 3100,
["Infobox_road2"] = 4200,
["Infobox_road2/hide/tourist"] = 4200,
["Infobox_road2/meta/errors"] = 4300,
["Infobox_road2/meta/mask/country"] = 4200,
["Infobox_royalty"] = 5800,
["Infobox_school"] = 4800,
["Infobox_scientist"] = 5600,
["Infobox_settlement"] = 203000,
["Infobox_settlement/areadisp"] = 129000,
["Infobox_settlement/columns"] = 38000,
["Infobox_settlement/densdisp"] = 197000,
["Infobox_settlement/impus"] = 4900,
["Infobox_settlement/lengthdisp"] = 61000,
["Infobox_settlement/link"] = 38000,
["Infobox_settlement/metric"] = 141000,
["Infobox_settlement/metric_only"] = 2700,
["Infobox_settlement/pref"] = 149000,
["Infobox_settlement_YS"] = 2500,
["Infobox_software"] = 3600,
["Infobox_song"] = 7600,
["Infobox_song/color"] = 7600,
["Infobox_song/link"] = 7600,
["Infobox_sportsperson"] = 5600,
["Infobox_sportsperson/core"] = 5600,
["Infobox_station"] = 33000,
["Infobox_street"] = 3400,
["Infobox_street/meta/length"] = 2200,
["Infobox_television"] = 5800,
["Infobox_university"] = 6200,
["Infobox_venue"] = 2100,
["Infobox_weapon"] = 3200,
["Infobox_writer"] = 4100,
["Infobox_羽球選手"] = 2500,
["Information"] = 9400,
["Infraspeciesbox"] = 4700,
["Infraspeciesbox/italic_check"] = 4700,
["Infraspeciesbox/search_wikidata"] = 5000,
["Instagram"] = 16000,
["Internal_link_helper/de"] = 13000,
["Internal_link_helper/en"] = 315000,
["Internal_link_helper/es"] = 6200,
["Internal_link_helper/fr"] = 15000,
["Internal_link_helper/it"] = 4000,
["Internal_link_helper/ja"] = 62000,
["Internal_link_helper/ko"] = 16000,
["Internal_link_helper/nl"] = 3000,
["Internal_link_helper/pl"] = 2900,
["Internal_link_helper/pt"] = 4100,
["Internal_link_helper/ru"] = 10000,
["Internal_link_helper/uk"] = 12000,
["Internal_link_helper/vi"] = 3500,
["Internal_link_helper/yue"] = 5000,
["Iowa-geo-stub"] = 2900,
["IsIP"] = 4700,
["Is_article"] = 10000,
["Is_italic_taxon"] = 180000,
["Isnumeric"] = 5900,
["Module:I18n"] = 185000,
["Module:I18n/complex_date"] = 30000,
["Module:I18n/date"] = 30000,
["Module:IPAc-en"] = 3200,
["Module:IPAc-en/data"] = 3200,
["Module:IPAc-en/phonemes"] = 3200,
["Module:IPAc-en/pronunciation"] = 3200,
["Module:IPAddress"] = 5200,
["Module:ISODate"] = 2800,
["Module:ISO_3166"] = 100000,
["Module:ISO_3166/data/National"] = 100000,
["Module:ISO_3166/data/US"] = 43000,
["Module:ISOdate"] = 30000,
["Module:Icon"] = 56000,
["Module:Icon/data"] = 56000,
["Module:IfUtil"] = 163000,
["Module:If_empty"] = 603000,
["Module:If_in_page"] = 676000,
["Module:If_mobile"] = 88000,
["Module:If_preview"] = 227000,
["Module:If_preview/configuration"] = 227000,
["Module:If_preview/styles.css"] = 227000,
["Module:Ilh"] = 509000,
["Module:Ilh/data"] = 509000,
["Module:Importance/convert"] = 657000,
["Module:Importance/data"] = 657000,
["Module:In_lang"] = 3400,
["Module:Infobox"] = 722000,
["Module:Infobox/styles.css"] = 688000,
["Module:Infobox3cols"] = 17000,
["Module:InfoboxImage"] = 647000,
["Module:InfoboxImageVariant"] = 29000,
["Module:InfoboxImageVariant2"] = 5200,
["Module:Infobox_VG"] = 5200,
["Module:Infobox_artist"] = 3600,
["Module:Infobox_artist/parameterListCV"] = 2300,
["Module:Infobox_mapframe"] = 103000,
["Module:Infobox_military_conflict"] = 5700,
["Module:Infobox_military_conflict/styles.css"] = 5700,
["Module:Infobox_road2"] = 4200,
["Module:Infobox_road2/color"] = 4200,
["Module:Infobox_road2/length"] = 4200,
["Module:Infobox_road2/locations"] = 4200,
["Module:Infobox_road2/map"] = 4200,
["Module:Italic_title"] = 33000,
}
41810e3b17a5b78e8a6ddab78320ce92d0663585
Module:Infobox/styles.css
828
136
281
280
2024-08-02T10:55:03Z
黑茶
2
导入1个版本
sanitized-css
text/css
/*
* This TemplateStyles sheet deliberately does NOT include the full set of
* infobox styles. We are still working to migrate all of the manual
* infoboxes. See [[MediaWiki talk:Common.css/to do#Infobox]]
* DO NOT ADD THEM HERE
*/
/*
* not strictly certain these styles are necessary since the modules now
* exclusively output infobox-subbox or infobox, not both
* just replicating the module faithfully
*/
.infobox-subbox {
padding: 0;
border: none;
margin: -3px;
width: auto;
min-width: 100%;
font-size: 100%;
clear: none;
float: none;
background-color: transparent;
}
.infobox-3cols-child {
margin: auto;
}
.infobox .navbar {
font-size: 100%;
}
/* T281642 */
body.skin-minerva .infobox-header,
body.skin-minerva .infobox-subheader,
body.skin-minerva .infobox-above,
body.skin-minerva .infobox-title,
body.skin-minerva .infobox-image,
body.skin-minerva .infobox-full-data,
body.skin-minerva .infobox-below {
text-align: center;
}
/* Dark theme: [[William_Wragg]], [[Coral_Castle]] */
html.skin-theme-clientpref-night .infobox-full-data:not(.notheme) > div:not(.notheme)[style] {
background: #1f1f23 !important;
/* switch with var( --color-base ) when supported. */
color: #f8f9fa;
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox-full-data:not(.notheme) div:not(.notheme) {
background: #1f1f23 !important;
/* switch with var( --color-base ) when supported. */
color: #f8f9fa;
}
}
html.skin-theme-clientpref-night .infobox td div:not(.notheme)[style] {
background: transparent !important;
color: var(--color-base,#202122);
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox td div:not(.notheme)[style] {
background: transparent !important;
color: var(--color-base,#202122);
}
}
html.skin-theme-clientpref-night .infobox td div.NavHead:not(.notheme)[style] {
background: transparent !important;
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .infobox td div.NavHead:not(.notheme)[style] {
background: transparent !important;
}
}
/* Since infobox is a table, many infobox templates take advantage of this to add columns and rows to the infobox itself rather than as part of a new table inside them. This class should be discouraged and removed on the long term, but allows us to at least identify these tables going forward
Currently in use on: [[Module:Infobox3cols]]
Fixes issue described in https://phabricator.wikimedia.org/F55300125 on Vector 2022.
*/
@media (min-width: 640px) {
body.skin--responsive .infobox-table {
display: table !important;
}
body.skin--responsive .infobox-table > caption {
display: table-caption !important;
}
body.skin--responsive .infobox-table > tbody {
display: table-row-group;
}
body.skin--responsive .infobox-table tr {
display: table-row !important;
}
body.skin--responsive .infobox-table th,
body.skin--responsive .infobox-table td {
padding-left: inherit;
padding-right: inherit;
}
}
6538c5ed546ba98bea13e31fe0117c4c56f572fd
Template:Demo
10
137
283
282
2024-08-02T10:55:04Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:Demo|main}}<noinclude>{{documentation}}</noinclude>
e458e378477c6077a01987f334fdc73bee48512c
Template:Template Pre
10
138
285
284
2024-08-02T10:55:04Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Demo]]
{{Redirect category shell|
{{移動重定向}}
}}
ca45b9d1eeba9e87cb533979d69ea5dcc0737bcf
Module:Demo
828
139
287
286
2024-08-02T10:55:05Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
--creates a frame object that cannot access any of the parent's args
--unless a table containing a list keys of not to inherit is provided
function disinherit(frame, onlyTheseKeys)
local parent = frame:getParent() or frame
local orphan = parent:newChild{}
orphan.getParent = parent.getParent --returns nil
orphan.args = {}
if onlyTheseKeys then
local family = {parent, frame}
for f = 1, 2 do
for k, v in pairs(family[f] and family[f].args or {}) do
orphan.args[k] = orphan.args[k] or v
end
end
parent.args = mw.clone(orphan.args)
setmetatable(orphan.args, nil)
for _, k in ipairs(onlyTheseKeys) do
rawset(orphan.args, k, nil)
end
end
return orphan, parent
end
function p.get(frame, arg, passArgs)
local orphan, frame = disinherit(frame, passArgs and {arg or 1})
local code, noWiki, preserve = frame.args[arg or 1] or ''
if code:match'nowiki' then
local placeholder, preserve = ('6'):char(), {}
code = mw.text.unstripNoWiki(code)
noWiki = code:gsub('%%', placeholder):gsub('<', '<'):gsub('>', '>')
for k in noWiki:gmatch('&.-;') do
if not preserve[k] then
preserve[k] = true
table.insert(preserve, (k:gsub('&', '&')))
noWiki = noWiki:gsub('(&.-;)', '%%%s')
end
end
noWiki = mw.text.nowiki(noWiki):format(unpack(preserve)):gsub(placeholder, '%%')
end
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
return {
source = noWiki or code,
output = orphan:preprocess(code):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
}
end
function p.main(frame, demoTable)
local show = demoTable or p.get(frame)
local args = show.frame.args
args.br = tonumber(args.br or 1) and ('<br>'):rep(args.br or 1) or args.br or ''
if show[args.result_arg] then
return show[args.result_arg]
end
return string.format('<pre%s>%s</pre>%s%s', args.style and string.format(" style='%s'", args.style) or '', show.source, args.br, show.output)
end
-- Alternate function to return an inline result
function p.inline(frame, demoTable)
local show = demoTable or p.get(frame)
local args = show.frame.args
if show[args.result_arg] then
return show[args.result_arg]
end
return string.format('<code%s>%s</code>%s%s', args.style and string.format(" style='%s'", args.style) or '', show.source, ' → ', show.output)
end
--passing of args into other module without preprocessing
function p.module(frame)
local orphan, frame = disinherit(frame, {
'demo_template',
'demo_module',
'demo_module_func',
'demo_main',
'demo_br',
'demo_result_arg',
'demo_kill_categories',
'nocat'
})
local template = frame.args.demo_template and 'Template:'..frame.args.demo_template
local demoFunc = frame.args.demo_module_func or 'main\n'
local demoModule = require('Module:' .. frame.args.demo_module)[demoFunc:match('^%s*(.-)%s*$')]
frame.args.br, frame.args.result_arg = frame.args.demo_br, frame.args.demo_result_arg
local kill_categories = frame.args.demo_kill_categories or frame.args.nocat
if demoModule then
local named = {insert = function(self, ...) table.insert(self, ...) return self end}
local source = {insert = named.insert, '{{', frame.args.demo_template or frame.args.demo_module, '\n'}
if not template then
source:insert(2, '#invoke:'):insert(4, '|'):insert(5, demoFunc)
end
local insertNamed = #source + 1
for k, v in pairs(orphan.args) do
local nan, insert = type(k) ~= 'number', {v}
local target = nan and named or source
target:insert'|'
if nan then
target:insert(k):insert'=':insert'\n'
table.insert(insert, 1, #target)
end
target:insert(unpack(insert))
local nowiki = v:match('nowiki')
if nowiki or v:match('{{.-}}') then
orphan.args[k] = frame:preprocess(nowiki and mw.text.unstripNoWiki(v) or v)
end
end
source:insert'}}'
table.insert(source, insertNamed, table.concat(named))
return p.main(orphan, {
source = mw.text.encode(table.concat(source), "<>'|=~"),
output = tostring(demoModule(orphan)):gsub(kill_categories and '%[%[Category.-%]%]' or '', ''),
frame = frame
})
else
return "ERROR: Invalid module function: "..demoFunc
end
end
return p
021b3b6a2d34baf26bbf17d89e1c22a2d1db6a11
Template:Infobox/doc
10
140
289
288
2024-08-02T10:55:06Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{Documentation subpage}}<!-- 请在本页最底部添加分类与跨语言链接。 -->
{{High-use|all-pages=yes}}
{{Lua|Module:Infobox}}
本模板为一系列「信息框」模板的元模板,亦即本模板用于构建其他模板。通常不建議在条目中直接使用此模板,但是如有需要,可以在個別「一次性」情況中直接使用。参见[[Help:信息框]]以获取创建通用信息框的进一步方法。
=== 用法 ===
本模板与{{tl|navbox}}的用法相似,但也有一些不同之处。表格中的每一行既可以是顶栏(header),也可以是成对的标签(label)与-{A|zh-hans:数据; zh-hant:資料;}-(data),甚至还可以只是一个数据单元。每行只能有一种状态,且具有优先级:当你将一行同时定义为顶栏与标签/数据对,那么标签/数据对的定义将会被忽略。
====編號====
為方便日後更改信息框格式,header和label/data行的編號不需要完全按照1、2、3……的加一順序編寫,可以在中間預留一些行編號不用,可避免將來如要增加新行時要把該行後面的行編號一併更改。
header和label/data行的編號不可以重複,例如不可以同時使用header1和label1/data1,請使用header1、label2/data2(舉例)。
如希望大量移動編號(如為加入新label需將所有之後的label數字加一),可考慮使用[[模块:IncrementParams]]。
=== 参数 ===
==== “查看/讨论/编辑/历史”链接 ====
;name : “查看/讨论/编辑/历史”链接需要指向模板页的名称(name)。你可以填写<nowiki>{{subst:PAGENAME}}</nowiki>。如果此参数未填,则“查看/讨论/编辑/历史”链接不会显示。
==== 标题 ====
{{Infobox
|title = 信息框外的标题文本
|data1 = (信息框的其余部分)
}}
{{Infobox
|above = 信息框内的标题文本
|data1 = (信息框的其余部分)
}}
有两种方式为一个信息框填入标题。一种是将标题填在信息框外,另一种则是填写在信息框内。根据需要,你可以选择其中的一种使用,亦或同时使用这两种标题,甚至都不使用(尽管我们不推荐这样做)。
;title : 填写在信息框表格外顶部的标题文本。
;above : 填写在信息框表格内顶部单元的标题文本。
==== 可选项 ====
;subheader : 在 above 下面的次標題。subheader2是第2個次標題。
;image : 在模板上部显示的图像。请使用完整的图像语法,例如<nowiki>[[File:example.png|200px]]</nowiki>,推荐使用[[模块:InfoboxImage]]插入图像。图像的位置默认为居中。<br/>在中文維基百科,一個Infobox最多可使用4個圖像參數:overimage(置頂)、image(=image1)、image2、image3,與英文維基百科的Infobox僅提供image(=image1)、image2不同。
;caption : 位于图像下方的说明文本。<br/>overcaption、caption(=caption1)、caption2、caption3分別對應上面4個圖像參數。
;header(n) : 填入第n行的'''顶栏'''文本。
;label(n): 填入第n行的'''标签'''文本。
;data(n): 填入第n行的'''数据'''文本。
;below: 填写在信息框表格底部单元的文本。底部单元一般用来填写脚注、参见及其他类似的信息。
==== 可选的CSS风格 ====
;bodystyle : 应用到信息框表格全体。
;titlestyle : 应用到信息框表格外的标题中。不建议在此处填写背景颜色(background color),因为该处的文字位于信息框外。
;abovestyle : 应用到信息框表格内顶部单元中。默认的风格为“<syntaxhighlight lang="css" inline>font-size:large;</syntaxhighlight>”(字号设为大号),因为该单元常被用作标题。如果你希望让顶部单元以正常字号显示,只需在该处填写的内容中包含“<syntaxhighlight lang="css" inline>font-size:medium;</syntaxhighlight>”。
;imagestyle : 应用到信息框的图像单元中,包括图像下方的说明文本。但是,出于兼容性与未来修改的考虑,如果你需要设置说明文本的属性,请使用captionstyle而不要使用imagestyle。
;captionstyle : 应用到图像说明文本中。
;headerstyle : 应用到所有的顶栏单元。
;header(n)style : 应用到第n行的顶栏单元。
;labelstyle : 应用到所有的标签单元。如果希望避免标签文字折行显示,只需在该处填写的内容中包含“<syntaxhighlight lang="css" inline>white-space:nowrap;</syntaxhighlight>”。或者例如“min-width: 4em;”。
;label(n)style : 应用到第n行的标签单元。
;datastyle : 应用到所有的数据单元。
;data(n)style : 应用到第n行的数据单元。
;belowstyle : 应用到底部单元中。
==== 微格式 ====
;bodyclass: 该参数影响信息框整体的类(class)。
;imageclass: 该参数影响图像的类。
;class(n): 该参数影响特定行数据单元的类。如果信息框没有数据单元,则不会产生作用。
;titleclass: 该参数影响信息框外标题的类。
;aboveclass: 该参数影响信息框内标题的类。
通过为各个数据单元定义类名,本模板可以支持[[微格式]]信息;此处所说的类名,是根据标准定义的,且可以向机器表明信息的类型。例如,如果一个信息框使用了[[hCard]]的微格式,要在信息框内标记此微格式,则填写以下参数:
<pre>
|bodyclass = vcard
</pre>
并为每一个包含了vcard所需数据单元的行添加相应的类参数:
<pre>
|class1 = fn
|class2 = org
|class3 = tel
</pre>
等等。用于显示信息框主题的“above”和“title”也可以指定类。
请在[[那艺娜维基:專題/微格式]]以获取在维基百科添加微格式信息的进一步信息,访问[http://microformats.org/wiki/Main_Page microformats.org]网站亦能获取更一般性的信息。
=== 表格域可选项 ===
如果表格的一行只有标签而没有数据,那么该行将不会显示。这样可以方便编者创建选填内容的行。要让某行成为可选项,只需填写一个默认为空字段的参数即可:
<pre>
|label5 = 人口
|data5 = {{{population|}}}
</pre>
这样的话,如果在条目中不定义“population”参数,则信息框的那一行不会被显示。
如果表格的一行填写的是预设格式内容(即除了参数外,还有其他内容),而又希望让该行成为可选项的话,你可以通过“#if”语句实现。当参数为空时,令所有的内容均不被呈现。譬如,在下面的例子里,“#if”会判断参数“mass”是否不为空,若不为空则显示它,并跟上“-{A|zh-hans:千克; zh-hant:公斤;}-”的后缀:
<pre>
|label6 = 质量
|data6 = {{#if:{{{mass|}}} |{{{mass}}}千克}}
</pre>
更多关于#if的用法,参见[[Help:模板扩展语法#if|此处]]。
如果你希望顶栏只在其下方的某个或多个数据单元有内容时才显示,以下的例子可以指导你如何实现:
<pre style="overflow:auto;">
{{Infobox
|name = {{subst:PAGENAME}}
|title = 可选顶栏的用例
|autoheaders = y
|header1 = 可选顶栏
|label2 = 项目一
|data2 = {{{item_one|}}}
|label3 = 项目二
|data3 = {{{item_two|}}}
|label4 = 项目三
|data4 = {{{item_three|}}}
}}
</pre>
这样,只有在参数“item_one”、“item_two”或“item_three”其中之一被填写时,“header1”才会被显示。如果上述三个参数均未被定义,则顶栏不会显示。
过去在实现这一功能时,需嵌套冗长的“#if”语法,现在只需设置{{para|autoheaders|y}}即可。
=== 用例 ===
{|style="border: 0px; width: 100%;"
|-
|{{Template Pre
|br = <td style="vertical-align: top;">
|demo_kill_categories =yes
|<nowiki>{{Infobox
|name = Infobox
|bodystyle =
|title = 测试信息框
|titlestyle =
|image = [[File:example.png|200px]]
|imagestyle =
|caption = Caption for example.png
|captionstyle =
|headerstyle = background:#ccf;
|labelstyle = background:#ddf;
|datastyle =
|header1 = 独自定义的顶栏
|label1 =
|data1 =
|header2 =
|label2 = 独自定义的标签
|data2 =
|header3 =
|label3 =
|data3 = 独自定义的数据
|header4 = 三项均有定义(顶栏)
|label4 = 三项均有定义(标签)——错误:因为有设顶栏而不会显示出来
|data4 = 三项均有定义(数据)——错误:因为有设顶栏而不会显示出来
|header5 =
|label5 = 标签和数据有定义(标签)
|data5 = 标签和数据有定义(数据)
|belowstyle = background:#ddf;
|below = 下方文本
}}</nowiki>}}
|}
注意到,当标签脱离数据单元单独定义时,所定义的那一行并未出现在信息框内;而当顶栏与标签、数据定义在同一栏时,顶栏将会优先显示。
{{clear}}
在下面的例子中,定义了“<code>{{nowrap|bodystyle {{=}} width:20em;}}</code>”和“<code>{{nowrap|labelstyle {{=}} width:33%;}}</code>”。
{{Infobox
|bodystyle = width:20em;
|name = Infobox
|title = 测试信息框
|titlestyle =
|headerstyle =
|labelstyle = width:33%;
|datastyle =
|header1 =
|label1 = 标签1
|data1 = 数据1
|header2 =
|label2 = 标签2
|data2 = 数据2
|header3 =
|label3 = 标签3
|data3 = 数据3
|header4 = 顶栏4
|label4 =
|data4 =
|header5 =
|label5 = 标签5
|data5 = 数据5:叽里呱啦稀里哗啦。
|belowstyle =
|below = 下方文本
}}
{{clear}}
=== 完整模板 ===
(备注:本模板目前最多可以同时处理80行表格,一般的信息框模板只会用到前20行的参数,因此此处省略了后60行的参数。需使用时可依此类推。微格式“class”参数亦被省略,因其不常被用到,使用时请自行添加。)
<pre style="overflow:auto;">
{{Infobox
| name = {{subst:PAGENAME}}
| child = {{{child|}}}
| subbox = {{{subbox|}}}
| italic title = {{{italic title|no}}}
| bodystyle =
| titlestyle =
| abovestyle =
| subheaderstyle =
| title =
| above =
| subheader =
| imagestyle =
| captionstyle =
| image =
| caption =
| image2 =
| caption2 =
| headerstyle =
| labelstyle =
| datastyle =
| header1 =
| label1 =
| data1 =
| header2 =
| label2 =
| data2 =
| header3 =
| label3 =
| data3 =
| header4 =
| label4 =
| data4 =
| header5 =
| label5 =
| data5 =
| header6 =
| label6 =
| data6 =
| header7 =
| label7 =
| data7 =
| header8 =
| label8 =
| data8 =
| header9 =
| label9 =
| data9 =
| header10 =
| label10 =
| data10 =
| belowstyle =
| below =
}}
</pre>
=== 参见 ===
* [[Special:前缀索引/Template:Infobox|所有以Template:Infobox为前缀的页面]]
<includeonly>
{{#ifeq:{{SUBPAGENAME}}|sandbox | |
[[Category:信息框模板|*]]
}}
</includeonly>
afea96bb12f9f666f8223d1caf978bdb0f2465c1
MediaWiki:Common.css
8
141
290
2024-08-02T11:00:36Z
黑茶
2
手动导入维基百科的样式
css
text/css
/* 这里放置的CSS将应用于所有皮肤 */
/* 所有皮肤的公共CSS */
/* 管理员注意!任何对Common.css的改变必须先在技术客栈讨论,谢谢。 */
/* .mw-parser-output内的样式调整请使用TemplateStyles */
/* Default styling for HTML elements */
cite,
dfn {
font-style: inherit; /* Reset default styling for <dfn> */
}
/*
== 参考区 ==
*/
/* Make the list of references smaller
* Keep in sync with Template:Refbegin/styles.css
* And Template:Reflist/styles.css
*/
ol.references,
div.reflist {
font-size: 90%; /* Default font-size */
margin-bottom: 0.5em;
}
div.reflist ol.references{
font-size: 100%; /* Reset font-size when nested in div.reflist */
}
div.reflist ol.references, div.notelist ol.references {
list-style-type: inherit; /* Enable custom list style types */
}
/* .references-2column b/c */
div.references-2column {
-moz-column-count: 2;
column-count: 2;
font-size: 90%;
}
div.references-2column ol.references,
div.references-2column div.reflist{
font-size: 100%;
}
/* T156351: Support for Parsoid's Cite implementation */
a[rel="mw:referencedBy"]::before {
font-weight: bold;
content: "^";
}
span[rel="mw:referencedBy"] > a::before {
font-weight: bold;
content: counter( mw-references, decimal ) '.' counter( mw-ref-linkback, decimal );
}
span[rel="mw:referencedBy"]::before {
content: "^ ";
}
.mw-ref > a[data-mw-group=upper-roman]::after {
content: '[' counter( mw-Ref, upper-roman ) ']';
}
.mw-ref > a[data-mw-group=lower-greek]::after {
content: '[' counter( mw-Ref, lower-greek ) ']';
}
.mw-ref > a[data-mw-group=lower-roman]::after {
content: '[' counter( mw-Ref, lower-roman ) ']';
}
.mw-ref > a[data-mw-group=lower-alpha]::after {
content: '[' counter( mw-Ref, lower-alpha ) ']';
}
.mw-ref > a[data-mw-group=upper-alpha]::after {
content: '[' counter( mw-Ref, upper-alpha ) ']';
}
/* Reduce page jumps by hiding collapsed/dismissed content */
.client-js .mw-special-Watchlist #watchlist-message,
.client-js .collapsible:not( .mw-made-collapsible).collapsed > tbody > tr:not(:first-child),
/* Avoid FOUC/reflows on collapsed elements. */
/* This copies MediaWiki's solution for T42812 to apply to innercollapse/outercollapse (T325115). */
/* TODO: Use :is() selector at some reasonable future when support is good for Most Clients */
/* Reference: https://gerrit.wikimedia.org/g/mediawiki/core/+/ecda06cb2aef55b77c4b4d7ecda492d634419ead/resources/src/jquery/jquery.makeCollapsible.styles.less#75 */
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > p,
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > table,
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) > thead + tbody,
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) tr:not( :first-child ),
.client-js .outercollapse .innercollapse.mw-collapsible:not( .mw-made-collapsible ) .mw-collapsible-content,
/* Reset top margin for lists embedded in columns */
div.columns {
margin-top: 0.3em;
}
div.columns dl,
div.columns ol,
div.columns ul {
margin-top: 0;
}
/* Avoid list items from breaking between columns */
div.columns li,
div.columns dd dd {
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid-column;
}
/* Prevent line breaks in silly places:
1) Where desired
2) Links when we don't want them to
3) Bold "links" to the page itself
4) HTML formulae
5) Ref tags with group names <ref group="Note"> --> "[Note 1]"
*/
.nowrap,
.nowraplinks a,
.nowraplinks .selflink,
span.texhtml,
sup.reference a {
white-space: nowrap;
}
/* Style for horizontal lists (separator following item) */
.hlist dl,
.hlist ol,
.hlist ul {
margin: 0;
}
.hlist dd,
.hlist dt,
.hlist li {
display: inline;
margin: 0;
}
/* Display nested lists inline */
.hlist.inline,
.hlist.inline dl,
.hlist.inline ol,
.hlist.inline ul,
.hlist dl dl, .hlist dl ol, .hlist dl ul,
.hlist ol dl, .hlist ol ol, .hlist ol ul,
.hlist ul dl, .hlist ul ol, .hlist ul ul {
display: inline;
}
/* Generate interpuncts */
.hlist dt:after {
content: " :";
}
.hlist dd:after,
.hlist li:after {
content: " · ";
font-weight: bold;
}
.hlist dd:last-child:after,
.hlist dt:last-child:after,
.hlist li:last-child:after {
content: none;
}
/* Add parens around nested lists */
.hlist dl dl:before,
.hlist ol ol:before,
.hlist ul ul:before {
content: "(";
}
.hlist dl dl:after,
.hlist ol ol:after,
.hlist ul ul:after {
content: ")";
}
/* Put numbers in ordered lists */
.hlist.hnum ol li {
counter-increment: level1;
}
.hlist.hnum ol li:before {
content: counter(level1) " ";
}
.hlist.hnum ol ol li {
counter-increment: level2;
}
.hlist.hnum ol ol li:before {
content: counter(level2) " ";
}
/* Unbulleted lists */
.plainlist ul {
line-height: inherit;
list-style: none none;
margin: 0;
}
.plainlist ul li {
margin-bottom: 0;
}
.same-bg { background: none }
/*
== 提示 ==
*/
/* Style for "notices" */
.notice {
text-align: justify;
margin: 1em;
padding: 0.2em;
}
#disambig {
border-top: 3px double var(--border-color-base,#a2a9b1);
border-bottom: 3px double var(--border-color-base,#a2a9b1);
}
#spoiler {
border-top: 2px solid var(--border-color-base,#a2a9b1);
border-bottom:2px solid var(--border-color-base,#a2a9b1);
}
/*
== 未归类 ==
*/
/* Infobox template style */
.infobox {
border: 1px solid var(--border-color-base,#a2a9b1);
border-spacing: 3px;
background-color: var(--background-color-neutral-subtle,#f8f9fa);
color: inherit;
margin: 0.5em 0 0.5em 1em;
padding: 0.2em;
float: right;
clear: right;
width: 22em;
}
.infobox td,
.infobox th {
vertical-align: top;
}
.infobox caption {
font-size: larger;
}
.infobox.bordered {
border-collapse: collapse;
}
.infobox.bordered td,
.infobox.bordered th {
border: 1px solid var(--border-color-base,#a2a9b1);
}
.infobox.bordered .borderless td,
.infobox.bordered .borderless th {
border: 0;
}
.infobox.sisterproject {
width: 20em;
font-size: 90%;
}
/* styles for bordered infobox with merged rows */
.infobox.bordered .mergedtoprow td,
.infobox.bordered .mergedtoprow th {
border: 0;
border-top: 1px solid var(--border-color-base,#a2a9b1);
border-right: 1px solid var(--border-color-base,#a2a9b1);
}
.infobox.bordered .mergedrow td,
.infobox.bordered .mergedrow th {
border: 0;
border-right: 1px solid var(--border-color-base,#a2a9b1);
}
/* styles for geography infoboxes, e.g. countries, country subdivisions, cities, etc. */
.infobox.geography {
text-align: left;
border-collapse: collapse;
line-height: 1.2em;
font-size: 90%;
}
.infobox.geography td,
.infobox.geography th {
border-top: solid 1px var(--border-color-base,#a2a9b1);
padding: 0.4em 0.6em 0.4em 0.6em;
}
.infobox.geography .mergedtoprow td,
.infobox.geography .mergedtoprow th {
border-top: solid 1px var(--border-color-base,#a2a9b1);
padding: 0.4em 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedrow td,
.infobox.geography .mergedrow th {
border: 0;
padding: 0 0.6em 0.2em 0.6em;
}
.infobox.geography .mergedbottomrow td,
.infobox.geography .mergedbottomrow th {
border-top: 0;
border-bottom: solid 1px var(--border-color-base,#a2a9b1);
padding: 0 0.6em 0.4em 0.6em;
}
.infobox.geography .maptable td,
.infobox.geography .maptable th {
border: 0;
padding: 0;
}
/* class hiddenStructure is defunct. See [[Wikipedia:hiddenStructure]] */
.hiddenStructure {
display: inline ! important;
color: var(--color-destructive--hover,#f00);
background-color: #0f0;
}
/* Removes underlines from certain links */
.nounderlines a {
text-decoration: none !important;
}
/* Custom link colors for use in [[MediaWiki:Edittools]] */
.charboxblack a:link, .charboxblack a:hover, .charboxblack a:visited, .charboxblack a:active { color: black; }
.charboxsilver a:link, .charboxsilver a:hover, .charboxsilver a:visited, .charboxsilver a:active { color: silver; }
.charboxgray a:link, .charboxgray a:hover, .charboxgray a:visited, .charboxgray a:active { color: gray; }
.charboxwhite a:link, .charboxwhite a:hover, .charboxwhite a:visited, .charboxwhite a:active { color: white; }
.charboxmaroon a:link, .charboxmaroon a:hover, .charboxmaroon a:visited, .charboxmaroon a:active { color: maroon; }
.charboxred a:link, .charboxred a:hover, .charboxred a:visited, .charboxred a:active { color: red; }
.charboxpurple a:link, .charboxpurple a:hover, .charboxpurple a:visited, .charboxpurple a:active { color: purple; }
.charboxfuchsia a:link, .charboxfuchsia a:hover, .charboxfuchsia a:visited, .charboxfuchsia a:active { color: fuchsia; }
.charboxgreen a:link, .charboxgreen a:hover, .charboxgreen a:visited, .charboxgreen a:active { color: green; }
.charboxlime a:link, .charboxlime a:hover, .charboxlime a:visited, .charboxlime a:active { color: lime; }
.charboxolive a:link, .charboxolive a:hover, .charboxolive a:visited, .charboxolive a:active { color: olive; }
.charboxyellow a:link, .charboxyellow a:hover, .charboxyellow a:visited, .charboxyellow a:active { color: yellow; }
.charboxnavy a:link, .charboxnavy a:hover, .charboxnavy a:visited, .charboxnavy a:active { color: navy; }
.charboxblue a:link, .charboxblue a:hover, .charboxblue a:visited, .charboxblue a:active { color: blue; }
.charboxteal a:link, .charboxteal a:hover, .charboxteal a:visited, .charboxteal a:active { color: teal; }
.charboxaqua a:link, .charboxaqua a:hover, .charboxaqua a:visited, .charboxaqua a:active { color: aqua; }
/*
== 未归类 ==
*/
/* Class styles */
/* Special characters list below edit window works better without underlining */
#editpage-specialchars a { text-decoration: none; }
#editpage-specialchars a:hover { text-decoration: underline; }
/* If you don't want to see special characters list at all,
put the following line in your User:You/monobook.css file
(and remove the slash-asterisk comments) */
/* #editpage-specialchars { display: none; } */
/* Hatnotes and disambiguation notices */
.hatnote {
/* @noflip */
font-size: small;
}
div.hatnote {
/* @noflip */
padding-left: 2em;
margin-bottom: 0.8em; /* 小于1.2可能会导致错行问题*/
margin-top: 0.8em;
/* background: url(//upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Disambig_gray.svg/26px-Disambig_gray.svg.png) no-repeat;*/
}
div.hatnote + div.hatnote {
margin-top: -0.5em;
}
/*
== 未归类 ==
/* custom edits */
/* Default style for navigation boxes */
.navbox { /* Navbox container style */
border: 1px solid #a2a9b1;
width: 100%;
margin: auto;
clear: both;
font-size: 88%;
text-align: center;
padding: 1px;
}
.navbox-inner,
.navbox-subgroup {
width: 100%;
}
.navbox th,
.navbox-title,
.navbox-abovebelow {
text-align: center; /* Title and above/below styles */
padding-left: 1em;
padding-right: 1em;
}
th.navbox-group { /* Group style */
white-space: nowrap;
/* @noflip */
text-align: right;
}
.navbox,
.navbox-subgroup {
background: #fdfdfd; /* Background color */
}
.navbox-list {
border-color: #fdfdfd; /* Must match background color */
}
.navbox th,
.navbox-title {
background:#ccf; /* Level 1 color */
position: relative;
}
.navbox-abovebelow,
th.navbox-group,
.navbox-subgroup .navbox-title {
background: #ddddff; /* Level 2 color */
}
.navbox-subgroup .navbox-group,
.navbox-subgroup .navbox-abovebelow {
background: #e6e6ff; /* Level 3 color */
}
.navbox-even {
background: #f7f7f7; /* Even row striping */
}
.navbox-odd {
background: transparent; /* Odd row striping */
}
table.navbox + table.navbox { /* Single pixel border between adjacent navboxes */
margin-top: -1px; /* (doesn't work for IE6, but that's okay) */
}
.navbox .hlist td dl,
.navbox .hlist td ol,
.navbox .hlist td ul,
.navbox td.hlist dl,
.navbox td.hlist ol,
.navbox td.hlist ul {
padding: 0.125em 0; /* Adjust hlist padding in navboxes */
}
.navbox .hlist dd,
.navbox .hlist dt,
.navbox .hlist li {
white-space: nowrap; /* Nowrap list items in navboxes */
}
.navbox .hlist dd dl,
.navbox .hlist dt dl,
.navbox .hlist li ol,
.navbox .hlist li ul {
white-space: normal; /* But allow parent list items to be wrapped */
}
ol + table.navbox,
ul + table.navbox {
margin-top: 0.5em; /* Prevent lists from clinging to navboxes */
}
/* Default styling for Navbar template */
.navbar {
display: inline;
font-weight: normal;
}
.navbar ul {
display: inline;
white-space: nowrap;
}
.navbar li {
word-spacing: -0.125em;
}
.navbar.mini li abbr[title] {
font-variant: small-caps;
border-bottom: none;
text-decoration: none;
cursor: inherit;
}
/* Navbar styling when nested in navbox */
.navbox .navbar {
display: block;
}
.navbox-title .navbar {
/* @noflip */
float: left;
/* @noflip */
text-align: left;
/* @noflip */
margin-right: 0.5em;
width: auto;
padding-left: 0.2em;
position: absolute;
left: 1em;
}
/* In navboxes, the show/hide button balances the v·d·e links
from [[Template:Navbar]], so they need to be the same width. */
.navbox .mw-collapsible-toggle {
margin-left: 0.5em;
position: absolute;
right: 1em;
}
/* For display uneditable section */
.noedit .editsection, .noedit .mw-editsection
{
display: none;
}
/*
== for some templates ==
Messagebox templates
*/
.messagebox {
border: 1px solid #a2a9b1;
background-color: #f8f9fa;
width: 80%;
margin: 0 auto 1em auto;
padding: .2em;
display: inherit; /* 臨時抑制 https://phabricator.wikimedia.org/T232553 及 https://gerrit.wikimedia.org/r/535738 的修改 */
}
.messagebox.merge {
border: 1px solid #c0b8cc;
background-color: #f0e5ff;
text-align: center;
}
.messagebox.cleanup {
border: 1px solid #9f9fff;
background-color: #efefff;
text-align: center;
}
.messagebox.standard-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
}
.messagebox.nested-talk {
border: 1px solid #c0c090;
background-color: #f8eaba;
width: 100%;
margin: 2px 4px 2px 4px;
}
.messagebox.small {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
}
.messagebox.small-talk {
width: 238px;
font-size: 85%;
float: right;
clear: both;
margin: 0 0 1em 1em;
line-height: 1.25em;
background: #f8f9fa;
}
/* For template documentation */
.template-documentation, #documentation-meta-data {
clear: both;
margin: 1em 0 0 0;
border: 1px solid #a2a9b1;
background-color: #ecfcf4;
padding: 5px;
}
html.skin-theme-clientpref-night .template-documentation,
html.skin-theme-clientpref-night #documentation-meta-data {
background-color: #0b1e1c;
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .template-documentation,
html.skin-theme-clientpref-os #documentation-meta-data {
background-color: #0b1e1c;
}
}
/*
== external link ==
Change the external link icon to an Adobe icon for all PDF files
(in browsers that support these CSS selectors, like Mozilla and Opera)
*/
#bodyContent a[href$=".pdf"].external,
#bodyContent a[href*=".pdf?"].external,
#bodyContent a[href*=".pdf#"].external,
#bodyContent a[href$=".PDF"].external,
#bodyContent a[href*=".PDF?"].external,
#bodyContent a[href*=".PDF#"].external {
background: url(//upload.wikimedia.org/wikipedia/commons/4/4d/Icon_pdf_file.png) center right no-repeat;
padding-right: 16px;
}
/*
== other ==
*/
span.lanLabel {
color: var(--color-placeholder,#72777d);
padding-left: 0.5em;
}
tt span.minor {
margin: 0 -2px 0 -3px;
font-size: 12px;
}
tt span.newpage {
margin: 0 1px 0 -6px;
font-size: 12px;
}
tt span.bot {
margin: 0 -6px 0 1px;
font-size: 12px;
}
/*tt span.unpatrolled*/
/* 用于封禁类模板,如Template:Uw-block1 */
div.user-block {
padding: 5px;
border: 1px solid var(--border-color-base,#a2a9b1);
background-color: var(--background-color-warning-subtle,#FFEFD5);
color: inherit;
}
/* For linked citation numbers and document IDs, where the number need not be shown on a screen or a handheld, but should be included in the printed version */
@media screen, handheld, projection {
cite *.printonly {
display: none;
}
}
/*
== MetaBox ==
*/
/*HERE FINISHES "METABOX" COLOUR-SCHEMES*/
/********************
**Styles for mboxes**
********************/
/* Cell sizes for ambox/tmbox/imbox/cmbox/ombox/fmbox/dmbox message boxes */
th.mbox-text, td.mbox-text { /* The message body cell(s) */
border: none;
padding: 0.25em 0.9em; /* 0.9em left/right */
width: 100%; /* Make all mboxes the same width regardless of text length */
}
td.mbox-image { /* The left image cell */
border: none;
padding: 2px 0 2px 0.9em; /* 0.9em left, 0px right */
text-align: center;
}
td.mbox-imageright { /* The right image cell */
border: none;
padding: 2px 0.9em 2px 0; /* 0px left, 0.9em right */
text-align: center;
}
td.mbox-empty-cell { /* An empty narrow cell */
border: none;
padding: 0px;
width: 1px;
}
/* Article message box styles */
table.ambox {
margin: 0px 10%; /* 10% = Will not overlap with other elements */
border: 1px solid #a2a9b1;
border-left: 10px solid #36c; /* Default "notice" blue */
background: #f8f9fa;
}
table.ambox + table.ambox { /* Single border between stacked boxes. */
margin-top: -1px;
}
.ambox th.mbox-text,
.ambox td.mbox-text { /* The message body cell(s) */
padding: 0.25em 0.5em; /* 0.5em left/right */
}
.ambox td.mbox-image { /* The left image cell */
padding: 2px 0 2px 0.5em; /* 0.5em left, 0px right */
}
.ambox td.mbox-imageright { /* The right image cell */
padding: 2px 0.5em 2px 0; /* 0px left, 0.5em right */
}
table.ambox-notice {
border-left: 10px solid #36c; /* Blue */
}
table.ambox-speedy {
border-left: 10px solid #b32424; /* Red */
background: #fee7e6; /* Pink */
}
table.ambox-delete {
border-left: 10px solid #b32424; /* Red */
}
table.ambox-content {
border-left: 10px solid #f28500; /* Orange */
}
table.ambox-style {
border-left: 10px solid #fc3; /* Yellow */
}
table.ambox-move {
border-left: 10px solid #9932cc; /* Purple */
}
table.ambox-protection {
border-left: 10px solid #a2a9b1; /* Gray-gold */
}
/* Image message box styles */
table.imbox {
margin: 4px 10%;
border-collapse: collapse;
border: 3px solid #36c; /* Default "notice" blue */
background: #f8f9fa;
}
.imbox .mbox-text .imbox { /* For imboxes inside imbox-text cells. */
margin: 0 -0.5em; /* 0.9 - 0.5 = 0.4em left/right. */
}
.mbox-inside .imbox { /* For imboxes inside other templates. */
margin: 4px;
}
table.imbox-notice {
border: 3px solid #36c; /* Blue */
}
table.imbox-speedy {
border: 3px solid #b32424; /* Red */
background: #fee7e6; /* Pink */
}
table.imbox-delete {
border: 3px solid #b32424; /* Red */
}
table.imbox-content {
border: 3px solid #f28500; /* Orange */
}
table.imbox-style {
border: 3px solid #fc3; /* Yellow */
}
table.imbox-move {
border: 3px solid #9932cc; /* Purple */
}
table.imbox-protection {
border: 3px solid #a2a9b1; /* Gray-gold */
}
table.imbox-license {
border: 3px solid #88a; /* Dark gray */
background: #f7f8ff; /* Light gray */
}
table.imbox-featured {
border: 3px solid #cba135; /* Brown-gold */
}
/* Category message box styles */
table.cmbox {
margin: 3px 10%;
border-collapse: collapse;
border: 1px solid #a2a9b1;
background: #eaf3ff; /* Default "notice" blue */
}
table.cmbox-notice {
background: #eaf3ff; /* Blue */
}
table.cmbox-speedy {
margin-top: 4px;
margin-bottom: 4px;
border: 4px solid #b32424; /* Red */
background: #fee7e6; /* Pink */
}
table.cmbox-delete {
background: #fee7e6; /* Red */
}
table.cmbox-content {
background: #FFE7CE; /* Orange */
}
table.cmbox-style {
background: #FFF9DB; /* Yellow */
}
table.cmbox-move {
background: #E4D8FF; /* Purple */
}
table.cmbox-protection {
background: #EFEFE1; /* Gray-gold */
}
/* Other pages message box styles */
.mw-parser-output .ombox {
margin:4px 0;
border-collapse:collapse;
border:1px solid #a2a9b1;
background-color:var(--background-color-neutral-subtle,#f8f9fa);
box-sizing:border-box;
color:var(--color-base,#202122)
}
.mw-parser-output .ombox.mbox-small {
font-size:88%;
line-height:1.25em
}
.mw-parser-output .ombox-speedy {
border:2px solid #b32424;
background-color:#fee7e6
}
.mw-parser-output .ombox-delete {
border:2px solid #b32424
}
.mw-parser-output .ombox-content {
border:1px solid #f28500
}
.mw-parser-output .ombox-style {
border:1px solid #fc3
}
.mw-parser-output .ombox-move {
border:1px solid #9932cc
}
.mw-parser-output .ombox-protection {
border:2px solid #a2a9b1
}
.mw-parser-output .ombox .mbox-text {
border:none;
padding:0.25em 0.9em;
width:100%
}
.mw-parser-output .ombox .mbox-image {
border:none;
padding:2px 0 2px 0.9em;
text-align:center
}
.mw-parser-output .ombox .mbox-imageright {
border:none;
padding:2px 0.9em 2px 0;
text-align:center
}
.mw-parser-output .ombox .mbox-empty-cell {
border:none;
padding:0;
width:1px
}
.mw-parser-output .ombox .mbox-invalid-type {
text-align:center
}
@media(min-width:720px) {
.mw-parser-output .ombox {
margin:4px 10%
}
.mw-parser-output .ombox.mbox-small {
clear:right;
float:right;
margin:4px 0 4px 1em;
width:238px
}
}
body.skin--responsive .mw-parser-output table.ombox img {
max-width:none!important
}
html.skin-theme-clientpref-night .mw-parser-output .ombox-speedy {
background-color:#310402
}
@media(prefers-color-scheme:dark) {
html.skin-theme-clientpref-os .mw-parser-output .ombox-speedy {
background-color:#310402
}
}
/* Talk page message box styles */
table.tmbox {
margin: 4px 10%;
border-collapse: collapse;
border: 1px solid #c0c090; /* Default "notice" gray-brown */
background: #f8eaba;
}
.mediawiki .mbox-inside .tmbox { /* For tmboxes inside other templates. The "mediawiki" */
margin: 2px 0; /* class ensures that this declaration overrides other */
width: 100%; /* For Safari and Opera */ /* styles (including mbox-small above) */
}
.mbox-inside .tmbox.mbox-small { /* "small" tmboxes should not be small when */
line-height: 1.5em; /* also "nested", so reset styles that are */
font-size: 100%; /* set in "mbox-small" above. */
}
table.tmbox-speedy {
border: 2px solid #b32424; /* Red */
background: #fee7e6; /* Pink */
}
table.tmbox-delete {
border: 2px solid #b32424; /* Red */
}
table.tmbox-content {
border: 2px solid #f28500; /* Orange */
}
table.tmbox-style {
border: 2px solid #fc3; /* Yellow */
}
table.tmbox-move {
border: 2px solid #9932cc; /* Purple */
}
table.tmbox-protection,
table.tmbox-notice {
border: 1px solid #c0c090; /* Gray-brown */
}
/* Disambig and set index box styles */
table.dmbox {
clear: both;
margin: 0.9em 1em;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: transparent;
font-size: small;
}
/* Footer and header message box styles */
table.fmbox {
clear: both;
margin: 0.2em 0;
width: 100%;
border: 1px solid #a2a9b1;
background-color: var(--background-color-interactive-subtle, #f8f9fa); /* Default "system" gray */
}
table.fmbox-system {
background-color: var(--background-color-interactive-subtle, #f8f9fa);
}
table.fmbox-warning {
border: 1px solid var(--border-color-error,#bb7070); /* Dark pink */
background: var(--background-color-error-subtle,#ffdbdb); /* Pink */
}
table.fmbox-editnotice {
background: transparent;
}
/* Div based "warning" style fmbox messages. */
div.mw-warning-with-logexcerpt,
div.mw-lag-warn-high,
div.mw-cascadeprotectedwarning,
#mw-protect-cascadeon {
clear: both;
margin: 0.2em 0;
border: 1px solid var(--border-color-error,#bb7070);
background: var(--background-color-error-subtle,#ffdbdb);
padding: 0.25em 0.9em;
}
/* Div based "system" style fmbox messages. Used in
[[MediaWiki:Noarticletext]]. */
div.noarticletext,
div.fmbox-system {
clear: both;
margin: 0.2em 0;
border: 1px solid var(--border-color-notice,#a2a9b1);
background: var(--background-color-notice-subtle,#f8f9fa);
padding: 0.25em 0.9em;
}
/* These mbox-small classes must be placed after all other
ambox/tmbox/ombox etc classes. "body.mediawiki" is so
they override "table.ambox + table.ambox" above. */
body.mediawiki table.mbox-small { /* For the "small=yes" option. */
clear: right;
float: right;
margin: 4px 0 4px 1em;
width: 238px;
font-size: 88%;
line-height: 1.25em;
}
body.mediawiki table.mbox-small-left { /* For the "small=left" option. */
margin: 4px 1em 4px 0;
width: 238px;
border-collapse: collapse;
font-size: 88%;
line-height: 1.25em;
}
/* CODE FOR COMPACT AMBOX */
/* Remove borders, backgrounds, padding, etc. */
.compact-ambox table.ambox {
border: none;
border-collapse: collapse;
background: transparent;
margin: 0 0 0 1.6em !important;
padding: 0 !important;
width: auto;
display: block;
}
body.mediawiki .compact-ambox table.mbox-small-left {
font-size: 100%;
width: auto;
margin: 0;
}
/* Style the text cell as a list item and remove its padding */
.compact-ambox table .mbox-text {
padding: 0 !important;
margin: 0 !important;
}
.compact-ambox table .mbox-text-span {
display: list-item;
line-height: 1.5em;
list-style-type: square;
list-style-image: url("data:image/gif;base64,R0lGODlhBQANAIAAAGOMnP///yH5BAEAAAEALAAAAAAFAA0AAAIJjI+pu+APo4SpADs=");
}
/* Style for compact ambox */
/* Hide the images */
.compact-ambox table .mbox-image,
.compact-ambox table .mbox-imageright,
.compact-ambox table .mbox-empty-cell {
display: none;
}
#siteNotice div {
margin: 0;
}
/* dark mode fix */
#siteNotice {
color: inherit;
}
#mw-dismissable-notice {
background:transparent;
}
#wpSummary, #wpSummaryLabel, input#wpSummary,input.mw-summary{
margin-top: 0;
margin-bottom: 0;
}
/* 解决cite定位内文字显示为斜体的问题 */
cite {
font-style: normal;
}
body:not(.skin-vector-search-vue) .mw-body>.firstHeading:lang(zh-hans):before, body:not(.skin-vector-search-vue) .mw-body>.firstHeading:lang(zh-cn):before, body:not(.skin-vector-search-vue) .mw-body>.firstHeading:lang(zh-my):before, body:not(.skin-vector-search-vue) .mw-body>.firstHeading:lang(zh-sg):before {
content: url(/static/images/mobile/copyright/wikipedia-wordmark-zh-hans.svg);
}
/* Pie chart test: Transparent borders */
.transborder {
border: solid var(--border-color-transparent,transparent);
}
/* http://zh.wikipedia.org/w/index.php?oldid=18291698#.E7.BB.B4.E5.9F.BA.E8.8D.A3.E8.AA.89.E5.A5.96.E5.8A.B1.E6.A8.A1.E6.9D.BF.E5.87.BA.E4.BA.86.E5.A4.A7.E9.97.AE.E9.A2.98 */
.ns-14 .mw-content-ltr > div[dir=ltr] {
clear: both;
}
/* [[template:fact]]的文字背景色设置 */
.template-facttext{
background-color: var(--background-color-neutral,#eaecf0);color: inherit; margin: -.3em 0; padding: .3em 0;
}
/* Hide stuff meant for accounts with special permissions. Made visible again in
[[MediaWiki:Group-sysop.css]], [[MediaWiki:Group-patroller.css]],
[[MediaWiki:Group-templateeditor.css]],
[[MediaWiki:Group-ipblock-exempt-grantor.css]],
[[MediaWiki:Group-extendedconfirmed.css]],
[[Mediawiki:Group-autoconfirmed.css]], and [[MediaWiki:Group-user.css]]. */
.sysop-show,
.patroller-show,
.templateeditor-show,
.ipblock-exempt-grantor-show,
.extendedconfirmed-show,
.autoconfirmed-show,
.user-show {
display: none;
}
/*编辑提交按钮部分的样式*/
.mw-summary-preset {
display: inline;
margin: 0;
padding: 0;
}
.mw-summary-preset-item {
border-left: 1px solid var(--border-color-base,#a2a9b1);
display: inline-block;
line-height: 1.25em;
margin: 0.125em 0;
padding: 0 0.5em;
}
.mw-summary-preset-item:first-child {
border-left: medium none;
padding-left: 0.25em;
}
.mw-summary-preset-item:last-child {
padding-right: 0.25em;
}
#pagehistory li.not-patrolled {
background-color: var(--background-color-warning-subtle,#FFA) !important;
}
/* HACK to workaround VE and badly written CGroups */
.noteTA {
display: none;
}
/* 页底文字太小 */
#footer ul li{
font-size:small;
}
/* 存废讨论旧样式 */
body.ns-4.action-view[class*=" page-Wikipedia_頁面存廢討論_"] .mw-parser-output .mw-heading2,
body.ns-4.action-view[class*=" page-Wikipedia_檔案存廢討論_"] .mw-parser-output .mw-heading2,
body.ns-4.action-submit[class*=" page-Wikipedia_頁面存廢討論_"] .mw-parser-output .mw-heading2,
body.ns-4.action-submit[class*=" page-Wikipedia_檔案存廢討論_"] .mw-parser-output .mw-heading2 {
border-bottom: none;
font-size: 132%;
margin-bottom: .3em;
}
body.ns-4.action-view[class*=" page-Wikipedia_頁面存廢討論_"] .mw-parser-output .mw-heading3,
body.ns-4.action-view[class*=" page-Wikipedia_檔案存廢討論_"] .mw-parser-output .mw-heading3,
body.ns-4.action-submit[class*=" page-Wikipedia_頁面存廢討論_"] .mw-parser-output .mw-heading3,
body.ns-4.action-submit[class*=" page-Wikipedia_檔案存廢討論_"] .mw-parser-output .mw-heading3 {
font-size: 116%;
margin-bottom: .3em;
}
/* For portals, added 2011-12-07 -bv
On wide screens, show these as two columns
On narrow and mobile screens, let them collapse into a single column */
.portal-column-left {
float: left;
width: 50%;
}
.portal-column-right {
float: right;
width: 49%;
}
.portal-column-left-wide {
float: left;
width: 60%;
}
.portal-column-right-narrow {
float: right;
width: 39%;
}
.portal-column-left-extra-wide {
float: left;
width: 70%;
}
.portal-column-right-extra-narrow {
float: right;
width: 29%;
}
@media only screen and (max-width: 800px) {
/* Decouple the columns on narrow screens */
.portal-column-left,
.portal-column-right,
.portal-column-left-wide,
.portal-column-right-narrow,
.portal-column-left-extra-wide,
.portal-column-right-extra-narrow {
float: inherit;
width: inherit;
}
}
#mw-content-text:lang(zh-Hans) .zhwiki-lang-zh-hant,
#mw-content-text:lang(zh-CN) .zhwiki-lang-zh-hant,
#mw-content-text:lang(zh-MY) .zhwiki-lang-zh-hant,
#mw-content-text:lang(zh-SG) .zhwiki-lang-zh-hant {
display: none;
}
#mw-content-text:lang(zh-Hant) .zhwiki-lang-zh-hans,
#mw-content-text:lang(zh-HK) .zhwiki-lang-zh-hans,
#mw-content-text:lang(zh-MO) .zhwiki-lang-zh-hans,
#mw-content-text:lang(zh-TW) .zhwiki-lang-zh-hans {
display: none;
}
/* Main page fixes */
#interwiki-completelist {
font-weight: bold;
}
/* MediaWiki:Tag-jimmy-bot-non-free */
.tag-jimmy-bot-non-free {
color: var(--color-error,red);
font-size: 1.143em;
}
/* Normal font styling for wikitable row headers with scope="row" tag */
.wikitable.plainrowheaders th[scope=row] {
font-weight: normal;
/* @noflip */
text-align: left;
}
/* mw-newarticletext */
.mw-newarticletext {
padding: 0 2.5em;
border: solid 1px var(--border-color-base,#a2a9b1);
}
.mw-newarticletext .title {
margin: 1em 0;
padding: 0;
color: var(--color-error,#d33);
font-size: 1.5em;
border: none;
text-align: center;
}
.mw-newarticletext li {
margin: 0.4em 0;
}
.mw-newarticletext .buttons {
margin: 1.5em 0;
text-align: center;
}
.mw-newarticletext .buttons a {
margin: 0.25em;
display: inline-block;
}
.mw-newarticletext .note {
color: var(--color-placeholder,#72777d);
font-size: 87.5%;
}
/* mw-newarticletextanon */
.mw-newarticletextanon {
padding: 0 2.5em;
border: solid 1px var(--border-color-base,#a2a9b1);
}
.mw-newarticletextanon .title {
margin: 1em 0;
padding: 0;
color: var(--color-error,#d33);
font-size: 1.5em;
border: none;
text-align: center;
}
.mw-newarticletextanon li {
margin: 0.4em 0;
}
.mw-newarticletextanon .buttons {
margin: 1.5em 0;
text-align: center;
}
.mw-newarticletextanon .buttons a {
margin: 0.25em;
display: inline-block;
}
.mw-newarticletextanon .note {
color: var(--color-placeholder,#72777d);
font-size: 87.5%;
}
/* 隱藏「編輯已選擇修訂的標籤」按鈕,參閱[[Special:日志/tag]]幾乎全是破壞,一堆使用者不懂該功能亂按,並造成**無法復原**的後果 */
.mw-history-editchangetags-button {
display: none;
}
.mw-log-editchangetags-button {
display: none;
}
/* 代码中间不换行 */
pre, .mw-code, .mw-highlight {
line-break: anywhere;
white-space: pre-wrap;
word-break: break-all;
}
/* Styling the parameter fields in [[Template:Information]] and related templates
also here (besides on [[MediaWiki:Filepage.css]]) to ensure proper preview
on other pages than those in the file namespace */
.fileinfo-paramfield {
background: #ccf;
/* @noflip */
text-align: right;
/* @noflip */
padding-right: 0.4em;
width: 15%;
font-weight: bold;
}
/* 由於有些使用者不了解此功能,所以我個人決定將其設定為opt-in功能 by Xiplus */
.mw-changeslist-src-mw-edit .unpatrolled {
display: none;
}
#mw-diff-ntitle4 .patrollink {
display: none;
}
/* RCP的wrapper是span,NPP的wrapper是div */
#mw-content-text span.patrollink {
display: none;
}
/* 修复Inline diffs中,"行内"两字发生断行 */
.mw-diffPage-inlineToggle-container {
white-space: nowrap;
}
/* Styling for JQuery makeCollapsible, matching that of collapseButton */
.mw-parser-output .mw-collapsible-toggle {
font-weight: normal;
/* @noflip */
text-align: right;
padding-right: 0.2em;
padding-left: 0.2em;
}
.mw-collapsible-leftside-toggle .mw-collapsible-toggle {
/* @noflip */
float: left;
/* @noflip */
text-align: left;
}
c915cef644da6219cf17192eaba7ad205baa6eb0
那艺娜维基 talk:沙盒
5
142
291
2024-08-02T11:04:12Z
黑茶
2
创建页面,内容为“该页面有内容导入从维基百科”
wikitext
text/x-wiki
该页面有内容导入从维基百科
5f83f19d65e9a1a32aac18339caeeb29624718d9
Meidawiki:newuserlogpage
0
144
293
2024-08-02T13:26:07Z
黑茶
2
创建页面,内容为“原神启动日志”
wikitext
text/x-wiki
原神启动日志
3edb9af5c8c49f3c2ff9b3118f8e8b1205cd530b
MediaWiki:Gadgets-definition
8
145
294
2024-08-03T02:54:01Z
黑茶
2
创建页面,内容为“* mygadget[ResourceLoader]|mygadget.js|mygadget.css”
wikitext
text/x-wiki
* mygadget[ResourceLoader]|mygadget.js|mygadget.css
d30d6fce0aa9019e593ea56a0ab75c5b8982dede
295
294
2024-08-03T02:57:26Z
黑茶
2
wikitext
text/x-wiki
* J-Tool[ResourceLoader]|jtool.js
90597f124a278d5732a7670588233c6a1d2c5e38
298
295
2024-08-03T03:05:40Z
黑茶
2
wikitext
text/x-wiki
* J-Tool[ResourceLoader]|Jtool.js
32c6ae46c3d6d78b4e645e49a648a0c06a41e4a2
MediaWiki:Gadget-J-Tool
8
146
296
2024-08-03T02:58:45Z
黑茶
2
创建页面,内容为“J-Tool”
wikitext
text/x-wiki
J-Tool
9d2309ad15f15e259024ad09cc992568067e3c78
MediaWiki:Jtool.js
8
147
297
2024-08-03T03:01:28Z
黑茶
2
创建页面,内容为“alert("jtool已加载")”
javascript
text/javascript
alert("jtool已加载")
cc80cfdb5d6de3e9043be5b9589cb5e02f13ea46
MediaWiki:Gadget-Jtool.js
8
148
299
2024-08-03T04:03:27Z
黑茶
2
创建页面,内容为“alert("测试")”
javascript
text/javascript
alert("测试")
efb31ec59cc846c15caf5fc6b0a74600f6054536
MediaWiki:Gadget-Twinkle
8
149
301
300
2024-08-03T04:07:14Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
[[WP:Twinkle|Twinkle]] <small>自动进行常见维护操作([[Wikipedia:Twinkle/参数设置|参数设置]])</small>
1c63a1a4c1c4467c0f7529cad174701ea722b434
MediaWiki:Gadget-Twinkle.js
8
150
303
302
2024-08-03T04:07:15Z
黑茶
2
导入1个版本
javascript
text/javascript
/**
* vim: set noet sts=0 sw=8:
* +-------------------------------------------------------------------------+
* | === 警告:全局小工具文件 === |
* | 对此文件的修改会影响许多用户。 |
* | 修改前请联系维护者。 |
* +-------------------------------------------------------------------------+
*
* 从Github导入 [https://github.com/Xi-Plus/twinkle]
* 所有修改都應該在儲存庫中進行,否則將在下次更新時遺失。
*
* ----------
*
* 这是Xiplus版本的Twinkle,是新手、管理员及他们之间的用户的
* 好帮手。请参见[[WP:TW]]以获取更多信息。
*/
// <nowiki>
/* global Morebits */
(function (window, document, $) { // Wrap with anonymous function
// Check if account is experienced enough to use Twinkle
if (!Morebits.userIsInGroup('autoconfirmed') && !Morebits.userIsInGroup('confirmed')) {
return;
}
var Twinkle = {};
window.Twinkle = Twinkle; // allow global access
var conv = require('ext.gadget.HanAssist').conv;
/**
* Twinkle-specific data shared by multiple modules
* Likely customized per installation
*/
// Custom change tag(s) to be applied to all Twinkle actions, create at Special:Tags
Twinkle.changeTags = 'Twinkle';
// Available for actions that don't (yet) support tags
// currently: FlaggedRevs and PageTriage
Twinkle.summaryAd = ' ([[WP:TW|TW]])';
// Various hatnote templates, used when tagging (csd/xfd/tag/prod/protect) to ensure [[w:en:MOS:ORDER]]
Twinkle.hatnoteRegex = '(?:Short[ _]description)|(?:Rellink|Hatnote|HAT)|(?:Main|细节|細節|Main[ _]articles|主条目|主條目|Hurricane[ _]main|条目|條目|主|頁面|页面|主頁面|主页面|主頁|主页|主題目|主题目|Main[ _]article|AP)|(?:Wrongtitle|Correct[ _]title)|(?:主条目消歧义|主條目消歧義|消歧义链接|消歧義鏈接|消歧義連結|消连|消連|消歧义连结|DisambLink|Noteref|Dablink)|(?:Distinguish|不是|Not|提示|混淆|分別|分别|區別|区别|本条目的主题不是|本條目的主題不是|本条目主题不是|本條目主題不是|条目主题不是|條目主題不是|主题不是|主題不是|Confused|区分|區分|Confusion|Confuse|RedirectNOT|Misspelling)|(?:Distinguish2|SelfDistinguish|Not2|不是2)|(?:For)|(?:Details|Further|See|另见|另見|More|相關條目|相关条目|Detail|见|見|更多资料|更多資料|Further[ _]information|更多资讯|更多資訊|More[ _]information|更多信息)|(?:Selfref)|(?:About|Otheruses4|关于|關於)|(?:Other[ _]uses|Otheruse|条目消歧义|條目消歧義|他用|Otheruses)|(?:Other[ _]uses list|Otheruselist|主條目消歧義列表|主条目消歧义列表|Otheruseslist|Aboutlist|About[ _]list|Otheruses[ _]list)|(?:Redirect|重定向至此|Redirects[ _]here|Redirect[ _]to)|(?:Redirect2|主條目消歧義2|主条目消歧义2|Redir|重定向至此2)|(?:Redirect3)|(?:Redirect4)|(?:Redirect-distinguish)|(?:Redirect-synonym)|(?:Redirect-multi)|(?:See[ _]Wiktionary|Seewikt)|(?:Seealso|参看|參看|See[ _]also|参见|參見|Also)|(?:See[ _]also2|Seealso2|不轉換參見|不转换参见)|(?:Other[ _]places)|(?:Contrast|對比|对比)';
Twinkle.initCallbacks = [];
/**
* Adds a callback to execute when Twinkle has loaded.
* @param {function} func
* @param {string} [name] - name of module used to check if is disabled.
* If name is not given, module is loaded unconditionally.
*/
Twinkle.addInitCallback = function twinkleAddInitCallback(func, name) {
Twinkle.initCallbacks.push({ func: func, name: name });
};
Twinkle.defaultConfig = {};
/**
* This holds the default set of preferences used by Twinkle.
* It is important that all new preferences added here, especially admin-only ones, are also added to
* |Twinkle.config.sections| in twinkleconfig.js, so they are configurable via the Twinkle preferences panel.
* For help on the actual preferences, see the comments in twinkleconfig.js.
*
* Formerly Twinkle.defaultConfig.twinkle and Twinkle.defaultConfig.friendly
*/
Twinkle.defaultConfig = {
// General
userTalkPageMode: 'tab',
dialogLargeFont: false,
disabledModules: Morebits.userIsSysop ? [] : ['block'], // default to disable block for non-sysop, if enable manually, they can only use it to tag userpage
disabledSysopModules: [],
// ARV
spiWatchReport: 'yes',
// Block
defaultToBlock64: false,
defaultToPartialBlocks: false,
blankTalkpageOnIndefBlock: false,
watchBlockNotices: 'yes',
customBlockReasonList: [],
// Fluff (revert and rollback)
openTalkPage: [ ],
openTalkPageOnAutoRevert: false,
rollbackInPlace: false,
markRevertedPagesAsMinor: [ 'vand' ],
watchRevertedPages: [ 'agf', 'norm', 'vand', 'torev' ],
watchRevertedExpiry: 'yes',
offerReasonOnNormalRevert: true,
confirmOnFluff: false,
confirmOnMobileFluff: true,
showRollbackLinks: [ 'diff', 'others' ],
customRevertSummary: [],
// DI (twinkleimage)
notifyUserOnDeli: true,
deliWatchPage: 'default',
deliWatchUser: 'default',
// Protect
watchRequestedPages: 'yes',
watchPPTaggedPages: 'default',
watchProtectedPages: 'default',
// CSD
speedySelectionStyle: 'buttonClick',
watchSpeedyPages: [ ],
watchSpeedyExpiry: 'yes',
markSpeedyPagesAsPatrolled: true,
// these next two should probably be identical by default
notifyUserOnSpeedyDeletionNomination: [ 'db', 'g1', 'g2', 'g3', 'g5', 'g11', 'g12', 'g13', 'g16', 'a1', 'a2', 'a5', 'a6', 'o7', 'o8', 'f6', 'r2', 'r3', 'r7' ],
welcomeUserOnSpeedyDeletionNotification: [ 'db', 'g1', 'g2', 'g3', 'g5', 'g11', 'g12', 'g13', 'g16', 'a1', 'a2', 'a5', 'a6', 'o7', 'o8', 'f6', 'r2', 'r3', 'r7' ],
promptForSpeedyDeletionSummary: [],
openUserTalkPageOnSpeedyDelete: [ ],
deleteTalkPageOnDelete: true,
deleteRedirectsOnDelete: true,
deleteSysopDefaultToDelete: false,
speedyWindowHeight: 500,
speedyWindowWidth: 800,
logSpeedyNominations: false,
speedyLogPageName: 'CSD日志',
noLogOnSpeedyNomination: [ 'o1' ],
enlargeG11Input: false,
// Unlink
unlinkNamespaces: [ '0', '10', '100', '102', '118' ],
// Warn
defaultWarningGroup: '1',
combinedSingletMenus: false,
showSharedIPNotice: true,
watchWarnings: 'yes',
oldSelect: false,
customWarningList: [],
autoMenuAfterRollback: false,
// XfD
logXfdNominations: false,
xfdLogPageName: 'AFD日志',
noLogOnXfdNomination: [],
xfdWatchDiscussion: 'default',
xfdWatchPage: 'default',
xfdWatchUser: 'default',
markXfdPagesAsPatrolled: true,
FwdCsdToXfd: Morebits.userIsSysop,
afdDefaultCategory: 'delete',
afdFameDefaultReason: '沒有足夠的可靠資料來源能夠讓這個條目符合[[Wikipedia:關注度]]中的標準',
afdSubstubDefaultReason: '過期小小作品',
XfdClose: Morebits.userIsSysop ? 'all' : 'hide',
// Copyvio
copyvioWatchPage: 'yes',
copyvioWatchUser: 'yes',
markCopyvioPagesAsPatrolled: true,
// Hidden preferences
autolevelStaleDays: 3,
revertMaxRevisions: 50, // intentionally limited
batchMax: 5000,
batchChunks: 50,
configPage: 'Wikipedia:Twinkle/参数设置',
projectNamespaceName: mw.config.get('wgFormattedNamespaces')[4],
sandboxPage: 'Wikipedia:沙盒',
// Deprecated options, as a fallback for add-on scripts/modules
summaryAd: ' ([[WP:TW|TW]])',
deletionSummaryAd: ' ([[WP:TW|TW]])',
protectionSummaryAd: ' ([[WP:TW|TW]])',
blockSummaryAd: ' ([[WP:TW|TW]])',
// Formerly defaultConfig.friendly:
// Tag
groupByDefault: true,
watchTaggedPages: 'yes',
watchMergeDiscussions: 'yes',
markTaggedPagesAsMinor: false,
markTaggedPagesAsPatrolled: true,
tagArticleSortOrder: 'cat',
customTagList: [],
customFileTagList: [],
customRedirectTagList: [],
// Stub
watchStubbedPages: false,
markStubbedPagesAsMinor: false,
markStubbedPagesAsPatrolled: true,
stubArticleSortOrder: 'cat',
customStubList: [],
// Welcome
topWelcomes: false,
watchWelcomes: 'yes',
welcomeHeading: conv({ hans: '欢迎', hant: '歡迎' }),
insertHeadings: true,
insertUsername: true,
insertSignature: true, // sign welcome templates, where appropriate
quickWelcomeMode: 'norm',
quickWelcomeTemplate: 'Welcome',
customWelcomeList: [],
customWelcomeSignature: true,
// Talkback
markTalkbackAsMinor: true,
insertTalkbackSignature: true, // always sign talkback templates
talkbackHeading: conv({ hans: '回复通告', hant: '回覆通告' }),
mailHeading: conv({ hans: '您有新邮件!', hant: '您有新郵件!' }),
// Shared
markSharedIPAsMinor: true
};
// now some skin dependent config.
switch (mw.config.get('skin')) {
case 'vector':
case 'vector-2022':
Twinkle.defaultConfig.portletArea = 'right-navigation';
Twinkle.defaultConfig.portletId = 'p-twinkle';
Twinkle.defaultConfig.portletName = 'TW';
Twinkle.defaultConfig.portletType = 'menu';
Twinkle.defaultConfig.portletNext = 'p-search';
break;
case 'timeless':
Twinkle.defaultConfig.portletArea = '#page-tools .sidebar-inner';
Twinkle.defaultConfig.portletId = 'p-twinkle';
Twinkle.defaultConfig.portletName = 'Twinkle';
Twinkle.defaultConfig.portletType = null;
Twinkle.defaultConfig.portletNext = 'p-userpagetools';
break;
default:
Twinkle.defaultConfig.portletArea = null;
Twinkle.defaultConfig.portletId = 'p-cactions';
Twinkle.defaultConfig.portletName = null;
Twinkle.defaultConfig.portletType = null;
Twinkle.defaultConfig.portletNext = null;
}
Twinkle.getPref = function twinkleGetPref(name) {
if (typeof Twinkle.prefs === 'object' && Twinkle.prefs[name] !== undefined) {
return Twinkle.prefs[name];
}
// Old preferences format, used before twinkleoptions.js was a thing
if (typeof window.TwinkleConfig === 'object' && window.TwinkleConfig[name] !== undefined) {
return window.TwinkleConfig[name];
}
if (typeof window.FriendlyConfig === 'object' && window.FriendlyConfig[name] !== undefined) {
return window.FriendlyConfig[name];
}
return Twinkle.defaultConfig[name];
};
/**
* **************** Twinkle.addPortlet() ****************
*
* Adds a portlet menu to one of the navigation areas on the page.
* This is necessarily quite a hack since skins, navigation areas, and
* portlet menu types all work slightly different.
*
* Available navigation areas depend on the skin used.
* Vector:
* For each option, the outer nav class contains "vector-menu", the inner div class is "vector-menu-content", and the ul is "vector-menu-content-list"
* "mw-panel", outer nav class contains "vector-menu-portal". Existing portlets/elements: "p-logo", "p-navigation", "p-interaction", "p-tb", "p-coll-print_export"
* "left-navigation", outer nav class contains "vector-menu-tabs" or "vector-menu-dropdown". Existing portlets: "p-namespaces", "p-variants" (menu)
* "right-navigation", outer nav class contains "vector-menu-tabs" or "vector-menu-dropdown". Existing portlets: "p-views", "p-cactions" (menu), "p-search"
* Special layout of p-personal portlet (part of "head") through specialized styles.
* Monobook:
* "column-one", outer nav class "portlet", inner div class "pBody". Existing portlets: "p-cactions", "p-personal", "p-logo", "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
* Special layout of p-cactions and p-personal through specialized styles.
* Modern:
* "mw_contentwrapper" (top nav), outer nav class "portlet", inner div class "pBody". Existing portlets or elements: "p-cactions", "mw_content"
* "mw_portlets" (sidebar), outer nav class "portlet", inner div class "pBody". Existing portlets: "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
*
* @param String navigation -- id of the target navigation area (skin dependant, on vector either of "left-navigation", "right-navigation", or "mw-panel")
* @param String id -- id of the portlet menu to create, preferably start with "p-".
* @param String text -- name of the portlet menu to create. Visibility depends on the class used.
* @param String type -- type of portlet. Currently only used for the vector non-sidebar portlets, pass "menu" to make this portlet a drop down menu.
* @param Node nextnodeid -- the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end.
*
* @return Node -- the DOM node of the new item (a DIV element) or null
*/
Twinkle.addPortlet = function(navigation, id, text, type, nextnodeid) {
// sanity checks, and get required DOM nodes
var root = document.getElementById(navigation) || document.querySelector(navigation);
if (!root) {
return null;
}
var item = document.getElementById(id);
if (item) {
if (item.parentNode && item.parentNode === root) {
return item;
}
return null;
}
var nextnode;
if (nextnodeid) {
nextnode = document.getElementById(nextnodeid);
}
// verify/normalize input
var skin = mw.config.get('skin');
if ((skin !== 'vector' && skin !== 'vector-2022') || (navigation !== 'left-navigation' && navigation !== 'right-navigation')) {
type = null; // menu supported only in vector's #left-navigation & #right-navigation
}
var outerNavClass, innerDivClass;
switch (skin) {
case 'vector':
case 'vector-2022':
// XXX: portal doesn't work
if (navigation !== 'portal' && navigation !== 'left-navigation' && navigation !== 'right-navigation') {
navigation = 'mw-panel';
}
outerNavClass = 'mw-portlet vector-menu';
if (navigation === 'mw-panel') {
outerNavClass += ' vector-menu-portal';
} else if (type === 'menu') {
outerNavClass += ' vector-menu-dropdown vector-dropdown vector-menu-dropdown-noicon';
} else {
outerNavClass += ' vector-menu-tabs';
}
innerDivClass = 'vector-menu-content vector-dropdown-content';
break;
case 'modern':
if (navigation !== 'mw_portlets' && navigation !== 'mw_contentwrapper') {
navigation = 'mw_portlets';
}
outerNavClass = 'portlet';
break;
case 'timeless':
outerNavClass = 'mw-portlet';
innerDivClass = 'mw-portlet-body';
break;
default:
navigation = 'column-one';
outerNavClass = 'portlet';
break;
}
// Build the DOM elements.
var outerNav, heading;
if (skin === 'vector-2022') {
outerNav = document.createElement('div');
heading = document.createElement('label');
} else {
outerNav = document.createElement('nav');
heading = document.createElement('h3');
}
outerNav.setAttribute('aria-labelledby', id + '-label');
// Vector getting vector-menu-empty FIXME TODO
outerNav.className = outerNavClass + ' emptyPortlet';
outerNav.id = id;
if (nextnode && nextnode.parentNode === root) {
root.insertBefore(outerNav, nextnode);
} else {
root.appendChild(outerNav);
}
heading.id = id + '-label';
var ul = document.createElement('ul');
if (skin === 'vector' || skin === 'vector-2022') {
heading.setAttribute('for', id + '-dropdown-checkbox');
ul.className = 'vector-menu-content-list';
heading.className = 'vector-menu-heading vector-dropdown-label';
// add invisible checkbox to keep menu open when clicked
// similar to the p-cactions ("More") menu
if (outerNavClass.indexOf('vector-menu-dropdown') !== -1) {
var chkbox = document.createElement('input');
chkbox.id = id + '-dropdown-checkbox';
chkbox.className = 'vector-menu-checkbox vector-dropdown-checkbox';
chkbox.setAttribute('type', 'checkbox');
chkbox.setAttribute('aria-labelledby', id + '-label');
outerNav.appendChild(chkbox);
// Vector gets its title in a span; all others except
// timeless have no title, and it has no span
var span = document.createElement('span');
span.appendChild(document.createTextNode(text));
heading.appendChild(span);
var a = document.createElement('a');
a.href = '#';
$(a).click(function(e) {
e.preventDefault();
});
heading.appendChild(a);
}
} else {
// Basically just Timeless
heading.appendChild(document.createTextNode(text));
}
outerNav.appendChild(heading);
if (innerDivClass) {
var innerDiv = document.createElement('div');
innerDiv.className = innerDivClass;
innerDiv.appendChild(ul);
outerNav.appendChild(innerDiv);
} else {
outerNav.appendChild(ul);
}
return outerNav;
};
/**
* **************** Twinkle.addPortletLink() ****************
* Builds a portlet menu if it doesn't exist yet, and add the portlet link.
* @param task: Either a URL for the portlet link or a function to execute.
*/
Twinkle.addPortletLink = function(task, text, id, tooltip) {
if (Twinkle.getPref('portletArea') !== null) {
Twinkle.addPortlet(Twinkle.getPref('portletArea'), Twinkle.getPref('portletId'), Twinkle.getPref('portletName'), Twinkle.getPref('portletType'), Twinkle.getPref('portletNext'));
}
var link = mw.util.addPortletLink(Twinkle.getPref('portletId'), typeof task === 'string' ? task : '#', text, id, tooltip);
$('.client-js .skin-vector #p-cactions').css('margin-right', 'initial');
if (typeof task === 'function') {
$(link).find('a').on('click', function (ev) {
task();
ev.preventDefault();
});
}
if ($.collapsibleTabs) {
$.collapsibleTabs.handleResize();
}
return link;
};
/**
* **************** General initialization code ****************
*/
var scriptpathbefore = mw.util.wikiScript('index') + '?title=',
scriptpathafter = '&action=raw&ctype=text/javascript&happy=yes';
// Retrieve the user's Twinkle preferences
$.ajax({
url: scriptpathbefore + 'User:' + encodeURIComponent(mw.config.get('wgUserName')) + '/twinkleoptions.js' + scriptpathafter,
dataType: 'text'
})
.fail(function () {
mw.notify(conv({ hans: '未能加载您的Twinkle参数设置', hant: '未能載入您的Twinkle偏好設定' }), { type: 'error' });
})
.done(function (optionsText) {
// Quick pass if user has no options
if (optionsText === '') {
return;
}
// Twinkle options are basically a JSON object with some comments. Strip those:
optionsText = optionsText.replace(/(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, '');
// First version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.
if (optionsText.lastIndexOf('window.Twinkle.prefs = ', 0) === 0) {
optionsText = optionsText.replace(/(?:^window.Twinkle.prefs = |;\n*$)/g, '');
}
try {
var options = JSON.parse(optionsText);
if (options) {
if (options.twinkle || options.friendly) { // Old preferences format
Twinkle.prefs = $.extend(options.twinkle, options.friendly);
} else {
Twinkle.prefs = options;
}
// v2 established after unification of Twinkle/Friendly objects
Twinkle.prefs.optionsVersion = Twinkle.prefs.optionsVersion || 1;
}
} catch (e) {
mw.notify(conv({ hans: '未能解析您的Twinkle参数设置', hant: '未能解析您的Twinkle偏好設定' }), { type: 'error' });
}
})
.always(function () {
$(Twinkle.load);
});
// Developers: you can import custom Twinkle modules here
// For example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);
Twinkle.load = function () {
// Don't activate on special pages other than those listed here, so
// that others load faster, especially the watchlist.
var activeSpecialPageList = [ 'Block', 'Contributions', 'AbuseLog', 'Recentchanges', 'Recentchangeslinked' ]; // wgRelevantUserName defined for non-sysops on Special:Block
if (Morebits.userIsSysop) {
activeSpecialPageList = activeSpecialPageList.concat([ 'DeletedContributions', 'Prefixindex', 'BrokenRedirects' ]);
}
if (mw.config.get('wgNamespaceNumber') === -1 &&
activeSpecialPageList.indexOf(mw.config.get('wgCanonicalSpecialPageName')) === -1) {
return;
}
// Prevent clickjacking
if (window.top !== window.self) {
return;
}
// Set custom Api-User-Agent header, for server-side logging purposes
Morebits.wiki.api.setApiUserAgent('Twinkle~zh (' + mw.config.get('wgWikiID') + ')');
Twinkle.disabledModules = Twinkle.getPref('disabledModules').concat(Twinkle.getPref('disabledSysopModules'));
// Redefine addInitCallback so that any modules being loaded now on are directly
// initialised rather than added to initCallbacks array
Twinkle.addInitCallback = function(func, name) {
if (!name || Twinkle.disabledModules.indexOf(name) === -1) {
func();
}
};
// Initialise modules that were saved in initCallbacks array
Twinkle.initCallbacks.forEach(function(module) {
Twinkle.addInitCallback(module.func, module.name);
});
// Increases text size in Twinkle dialogs, if so configured
if (Twinkle.getPref('dialogLargeFont')) {
mw.util.addCSS('.morebits-dialog-content, .morebits-dialog-footerlinks { font-size: 100% !important; } ' +
'.morebits-dialog input, .morebits-dialog select, .morebits-dialog-content button { font-size: inherit !important; }');
}
// Hide the lingering space if the TW menu is empty
var isVector = mw.config.get('skin') === 'vector' || mw.config.get('skin') === 'vector-2022';
if (isVector && Twinkle.getPref('portletType') === 'menu' && $('#p-twinkle').length === 0) {
$('#p-cactions').css('margin-right', 'initial');
}
};
/** Twinkle-specific utility functions shared by multiple modules */
// Used in batch, unlink, and deprod to sort pages by namespace, as
// json formatversion=2 sorts by pageid instead (#1251)
Twinkle.sortByNamespace = function(first, second) {
return first.ns - second.ns || (first.title > second.title ? 1 : -1);
};
// Used in deprod and unlink listings to link the page title
Twinkle.generateBatchPageLinks = function (checkbox) {
var $checkbox = $(checkbox);
var link = Morebits.htmlNode('a', $checkbox.val());
link.setAttribute('class', 'tw-batchpage-link');
link.setAttribute('href', mw.util.getUrl($checkbox.val()));
link.setAttribute('target', '_blank');
$checkbox.next().prepend([link, ' ']);
};
}(window, document, jQuery)); // End wrap with anonymous function
// </nowiki>
9317c10b81f37e8b15255a97a8890a101b63c23e
MediaWiki:Gadget-twinklearv.js
8
151
305
304
2024-08-03T04:07:16Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklearv.js: ARV module
****************************************
* Mode of invocation: Tab ("ARV")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.arv = function twinklearv() {
var username = Morebits.wiki.flow.relevantUserName(true);
if (!username) {
return;
}
var isIP = mw.util.isIPAddress(username);
var title = isIP ? conv({ hans: '报告IP给管理员', hant: '報告IP給管理員' }) : conv({ hans: '报告用户给管理人员', hant: '報告使用者給管理人員' });
Twinkle.addPortletLink(function() {
Twinkle.arv.callback(username, isIP);
}, conv({ hans: '告状', hant: '告狀' }), 'tw-arv', title);
};
Twinkle.arv.callback = function (uid, isIP) {
if (uid === mw.config.get('wgUserName')) {
alert(conv({ hans: '你不想报告你自己,对吧?', hant: '你不想報告你自己,對吧?' }));
return;
}
var Window = new Morebits.simpleWindow(600, 500);
Window.setTitle(conv({ hans: '报告用户给管理人员', hant: '報告使用者給管理人員' }));
Window.setScriptName('Twinkle');
Window.addFooterLink('VIP', 'WP:VIP');
Window.addFooterLink('EWIP', 'WP:EWIP');
Window.addFooterLink('UAA', 'WP:UAA');
Window.addFooterLink(conv({ hans: '用户名方针', hant: '使用者名稱方針' }), 'WP:U');
Window.addFooterLink('SPI', 'WP:SPI');
Window.addFooterLink(conv({ hans: '告状设置', hant: '告狀設定' }), 'WP:TW/PREF#arv');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'H:TW#告狀');
var form = new Morebits.quickForm(Twinkle.arv.callback.evaluate);
var categories = form.append({
type: 'select',
name: 'category',
label: conv({ hans: '选择报告类型:', hant: '選擇報告類別:' }),
event: Twinkle.arv.callback.changeCategory
});
categories.append({
type: 'option',
label: conv({ hans: '破坏(WP:VIP)', hant: '破壞(WP:VIP)' }),
value: 'aiv'
});
categories.append({
type: 'option',
label: conv({ hans: '编辑争议(WP:EWIP)', hant: '編輯爭議(WP:EWIP)' }),
value: 'ewip'
});
categories.append({
type: 'option',
label: conv({ hans: '用户名(WP:UAA)', hant: '使用者名稱(WP:UAA)' }),
value: 'username',
disabled: mw.util.isIPAddress(uid)
});
categories.append({
type: 'option',
label: conv({ hans: '傀儡调查(WP:SPI)', hant: '傀儡調查(WP:SPI)' }),
value: 'spi'
});
form.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-arv-blockwarning'
});
form.append({
type: 'field',
label: 'Work area',
name: 'work_area'
});
form.append({ type: 'submit', label: '提交' });
form.append({
type: 'hidden',
name: 'uid',
value: uid
});
var result = form.render();
Window.setContent(result);
Window.display();
// Check if the user is blocked, update notice
var query = {
action: 'query',
list: 'blocks',
bkprop: 'range|flags',
format: 'json'
};
if (isIP) {
query.bkip = uid;
} else {
query.bkusers = uid;
}
new Morebits.wiki.api(conv({ hans: '检查用户的封禁状态', hant: '檢查使用者的封鎖狀態' }), query, function (apiobj) {
var blocklist = apiobj.getResponse().query.blocks;
if (blocklist.length) {
var block = blocklist[0];
var message = (isIP ? conv({ hans: '此IP地址', hant: '此IP位址' }) : conv({ hans: '此账户', hant: '此帳號' })) + conv({ hans: '已经被', hant: '已經被' }) + (block.partial ? '部分' : '');
// Start and end differ, range blocked
message += block.rangestart !== block.rangeend ? conv({ hans: '段封禁。', hant: '段封鎖。' }) : conv({ hans: '封禁。', hant: '封鎖。' });
if (block.partial) {
$('#twinkle-arv-blockwarning').css('color', 'black'); // Less severe
}
$('#twinkle-arv-blockwarning').text(message);
}
}).post();
// We must init the
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.category.dispatchEvent(evt);
};
Twinkle.arv.lta_list = [
{ value: '', label: conv({ hans: '请选择', hant: '請選擇' }) },
{ value: 'Adam Asrul', label: 'Adam Asrul、ADAM' },
{ value: 'Albert20009', label: 'Albert20009' },
{ value: 'Kapol6360', label: 'Kapol6360、Kapol' },
{ value: 'R1t5', label: conv({ hans: '114.27、数论和人瑞类条目破坏、R1t5', hant: '114.27、數論和人瑞類條目破壞、R1t5' }) },
{ value: 'Royalfanta', label: 'Royalfanta、RF' },
{ value: 'Xayahrainie43', label: 'Xayahrainie43、X43、妍欣' },
{ value: '米記123', label: '米記123' }
];
Twinkle.arv.callback.pick_lta = function twinklearvCallbackPickLta(e) {
e.target.form.sockmaster.value = e.target.value;
Twinkle.arv.callback.spi_notice(e.target.form, e.target.value);
Twinkle.arv.callback.set_sockmaster(e.target.value);
e.target.value = '';
};
Twinkle.arv.callback.sockmaster_changed = function twinklearvCallbackSockmasterChanged(e) {
Twinkle.arv.callback.spi_notice(e.target.form, e.target.value);
Twinkle.arv.callback.set_sockmaster(e.target.value);
};
Twinkle.arv.callback.spi_notice = function twinklearvCallbackSpiNotice(form, sockmaster) {
var previewText = '{{#ifexist:Wikipedia:傀儡調查/案件/' + sockmaster +
'|{{#ifexist:Wikipedia:傀儡調查/案件通告/' + sockmaster +
' |<div class="extendedconfirmed-show sysop-show">{{Memo|1={{Wikipedia:傀儡調查/案件通告/' + sockmaster + '}}|2=notice}}</div>' +
' |無案件通告}}' +
'|您將建立新的提報頁面,如果您希望提報過往曾被提報過的使用者,請檢查您的輸入是否正確。}}';
form.spinoticepreviewer.beginRender(previewText, 'Wikipedia:傀儡調查/案件/' + sockmaster);
};
Twinkle.arv.callback.set_sockmaster = function twinklearvCallbackSetSockmaster(sockmaster) {
$('code.tw-arv-sockmaster').text('{{subst:Socksuspectnotice|1=' + sockmaster + '}}');
};
Twinkle.arv.callback.changeCategory = function (e) {
var value = e.target.value;
var root = e.target.form;
var old_area = Morebits.quickForm.getElements(root, 'work_area')[0];
var work_area = null;
var previewlink = document.createElement('a');
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
$(previewlink).on('click', function() {
Twinkle.arv.callback.preview(root);
});
switch (value) {
case 'aiv':
/* falls through */
default:
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告用户破坏', hant: '報告使用者破壞' }),
name: 'work_area'
});
work_area.append({
type: 'div',
label: conv({ hans: '提报傀儡应优先发送至傀儡调查,除非相关的账户有高频率、涉及多个页面等紧急严重的破坏行为。', hant: '提報傀儡應優先發送至傀儡調查,除非相關的帳號有高頻率、涉及多個頁面等緊急嚴重的破壞行為。' })
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '相关页面:', hant: '相關頁面:' }),
tooltip: conv({ hans: '如不希望让报告链接到页面,请留空', hant: '如不希望讓報告連結到頁面,請留空' }),
value: mw.util.getParamValue('vanarticle') || '',
event: function(e) {
var value = e.target.value;
var root = e.target.form;
if (value === '') {
root.badid.disabled = root.goodid.disabled = true;
} else {
root.badid.disabled = false;
root.goodid.disabled = root.badid.value === '';
}
}
});
work_area.append({
type: 'input',
name: 'badid',
label: conv({ hans: '受到破坏的修订版本:', hant: '受到破壞的修訂版本:' }),
tooltip: conv({ hans: '留空以略过差异', hant: '留空以略過差異' }),
value: mw.util.getParamValue('vanarticlerevid') || '',
disabled: !mw.util.getParamValue('vanarticle'),
event: function(e) {
var value = e.target.value;
var root = e.target.form;
root.goodid.disabled = value === '';
}
});
work_area.append({
type: 'input',
name: 'goodid',
label: conv({ hans: '破坏前的修订版本:', hant: '破壞前的修訂版本:' }),
tooltip: conv({ hans: '留空以略过差异的较早版本', hant: '留空以略過差異的較早版本' }),
value: mw.util.getParamValue('vanarticlegoodrevid') || '',
disabled: !mw.util.getParamValue('vanarticle') || mw.util.getParamValue('vanarticlerevid')
});
work_area.append({
type: 'checkbox',
name: 'arvtype',
list: [
{
label: conv({ hans: '已发出最后(层级4或4im)警告', hant: '已發出最後(層級4或4im)警告' }),
value: 'final'
},
{
label: conv({ hans: '封禁过期后随即破坏', hant: '封鎖過期後隨即破壞' }),
value: 'postblock'
},
{
label: conv({ hans: '显而易见的纯破坏用户', hant: '顯而易見的純破壞使用者' }),
value: 'vandalonly',
disabled: mw.util.isIPAddress(root.uid.value)
},
{
label: conv({ hans: '显而易见的spambot或失窃账户', hant: '顯而易見的spambot或失竊帳號' }),
value: 'spambot'
},
{
label: conv({ hans: '仅用来散发广告宣传的用户', hant: '僅用來散發廣告宣傳的使用者' }),
value: 'promoonly',
disabled: mw.util.isIPAddress(root.uid.value)
}
]
});
if (!mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName(true))) {
work_area.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '在页面上及编辑摘要隐藏用户名', hant: '在頁面上及編輯摘要隱藏使用者名稱' }),
tooltip: conv({ hans: '若用户名不当请勾选此项,注意:请考虑私下联系管理员处理。', hant: '若使用者名稱不當請勾選此項,注意:請考慮私下聯絡管理員處理。' }),
name: 'hidename',
value: 'hidename'
}
]
});
}
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'ewip':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告编辑争议', hant: '報告編輯爭議' }),
name: 'work_area'
});
work_area.append(
{
type: 'dyninput',
name: 'page',
label: conv({ hans: '相关页面:', hant: '相關頁面:' }),
sublabel: conv({ hans: '页面:', hant: '頁面:' }),
tooltip: conv({ hans: '如不希望让报告链接到页面,请留空', hant: '如不希望讓報告連結到頁面,請留空' }),
min: 1,
max: 10
});
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'username':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '报告不当用户名', hant: '報告不當使用者名稱' }),
name: 'work_area'
});
work_area.append({
type: 'header',
label: conv({ hans: '不当用户名类型', hant: '不當使用者名稱類別' }),
tooltip: conv({
hans: '维基百科不允许使用带有误导性、宣传性、侮辱性或破坏性的用户名。此外,使用域名及邮箱地址的用户名亦被禁止。这些准则俱应应用至用户名及签名。在其他语言中不当的用户名或通过错拼、替代、暗示、拆字或任何间接方法达成的非妥当用户名同样视为违规。', hant:
'維基百科不允許使用帶有誤導性、宣傳性、侮辱性或破壞性的使用者名稱。此外,使用域名及電子信箱位址的使用者名稱亦被禁止。這些準則俱應應用至使用者名稱及簽名。在其他語言中不當的使用者名稱或通過錯拼、替代、暗示、拆字或任何間接方法達成的非妥當使用者名稱同樣視為違規。'
})
});
work_area.append({
type: 'checkbox',
name: 'arvtype',
list: [
{
label: conv({ hans: '误导性用户名', hant: '誤導性使用者名稱' }),
value: conv({ hans: '误导性', hant: '誤導性' }),
tooltip: conv({
hans: '误导性用户名隐含着与贡献者相关或误导他人的事情。例如︰不实观点、暗示账户拥有特定权限或暗示该账户并非由一人拥有而是由一个组群、一个项目或一个集体运作。', hant:
'誤導性使用者名稱隱含著與貢獻者相關或誤導他人的事情。例如︰不實觀點、暗示帳戶擁有特定權限或暗示該帳戶並非由一人擁有而是由一個群組、一個計畫或一個集體運作。'
})
},
{
label: conv({ hans: '宣传性用户名', hant: '宣傳性使用者名稱' }),
value: conv({ hans: '宣传性', hant: '宣傳性' }),
tooltip: conv({ hans: '宣传性用户名会于维基百科上起推销一个组群或一间公司的作用。', hant: '宣傳性使用者名稱會於維基百科上起推銷一個群組或一間公司的作用。' })
},
{
label: conv({ hans: '暗示并非由一人拥有', hant: '暗示並非由一人擁有' }),
value: 'shared',
tooltip: conv({ hans: '每个维基账户只可以代表个人(容许一些例外情况),所有与他人分享账户的行为(包括分享账户密码)均被禁止。', hant: '每個維基帳戶只可以代表個人(容許一些例外情況),所有與他人分享帳戶的行為(包括分享帳戶密碼)均被禁止。' })
},
{
label: conv({ hans: '侮辱性用户名', hant: '侮辱性使用者名稱' }),
value: '侮辱性',
tooltip: conv({ hans: '侮辱性用户名令协调编辑变得困难,甚至无可能。', hant: '侮辱性使用者名稱令協調編輯變得困難,甚至無可能。' })
},
{
label: conv({ hans: '破坏性用户名', hant: '破壞性使用者名稱' }),
value: conv({ hans: '破坏性', hant: '破壞性' }),
tooltip: conv({ hans: '破坏性用户名包括人身攻击、伪冒他人或其他一切有着清晰可见的破坏维基百科意图的用户名。', hant: '破壞性使用者名稱包括人身攻擊、偽冒他人或其他一切有著清晰可見的破壞維基百科意圖的使用者名稱。' })
}
]
});
work_area.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '在页面上隐藏用户名(需监督的用户名请勿于站内报告,勾选此项并不构成能在站内报告的理由)', hant: '在頁面上隱藏使用者名稱(需監督的使用者名稱請勿於站內報告,勾選此項並不構成能在站內報告的理由)' }),
tooltip: conv({ hans: '若用户名不当请勾选此项,注意:请考虑私下联系管理员处理。', hant: '若使用者名稱不當請勾選此項,注意:請考慮私下聯絡管理員處理。' }),
name: 'hidename',
value: 'hidename'
}
],
style: 'font-weight: bold;'
});
work_area.append({
type: 'textarea',
name: 'reason',
label: conv({ hans: '评论:', hant: '評論:' })
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
case 'spi':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '发起傀儡调查', hant: '發起傀儡調查' }),
name: 'work_area'
});
work_area.append({
type: 'select',
name: 'common_lta',
label: '持續出沒的破壞者:',
style: 'width: 420px;',
list: Twinkle.arv.lta_list,
event: Twinkle.arv.callback.pick_lta
});
work_area.append({
type: 'input',
name: 'sockmaster',
label: $('<a>', {
href: mw.util.getUrl('Special:PrefixIndex/Wikipedia:傀儡調查/案件/'),
text: 'Wikipedia:傀儡調查/案件/',
target: '_blank'
})[0],
tooltip: conv({ hans: '主账户的用户名(不含User:前缀),这被用于创建傀儡调查子页面的标题,可在 Wikipedia:傀儡调查/案件 的子页面搜索先前的调查。', hant: '主帳號的使用者名稱(不含User:字首),這被用於建立傀儡調查子頁面的標題,可在 Wikipedia:傀儡調查/案件 的子頁面搜尋先前的調查。' }),
value: root.uid.value,
event: Twinkle.arv.callback.sockmaster_changed
});
work_area.append({ type: 'div', id: 'twinklearv-spinoticebox', style: 'display: none' });
work_area.append({
type: 'dyninput',
name: 'sockpuppet',
label: '傀儡',
sublabel: '傀儡:',
tooltip: conv({ hans: '傀儡的用户名(不含User:前缀)', hant: '傀儡的使用者名稱(不含User:字首)' }),
min: 2,
max: 9
});
work_area.append({
type: 'textarea',
label: conv({ hans: '证据:', hant: '證據:' }),
name: 'reason',
tooltip: conv({ hans: '输入能够用来体现这些用户可能滥用多重账户的证据,这通常包括互助客栈发言、页面历史或其他有关的信息。请避免在此处提供非与傀儡或滥用多重账户相关的其他讨论。', hant: '輸入能夠用來體現這些使用者可能濫用多重帳號的證據,這通常包括互助客棧發言、頁面歷史或其他有關的資訊。請避免在此處提供非與傀儡或濫用多重帳號相關的其他討論。' })
});
work_area.append({
type: 'checkbox',
list: [{
label: conv({ hans: '请求用户查核', hant: '請求使用者查核' }),
name: 'checkuser',
tooltip: conv({ hans: '用户查核是一种用于获取傀儡指控相关技术证据的工具,若没有正当理由则不会使用,您必须在证据字段充分解释为什么需要使用该工具。用户查核不会用于公开连接用户账户使用的IP地址。', hant: '使用者查核是一種用於獲取傀儡指控相關技術證據的工具,若沒有正當理由則不會使用,您必須在證據欄位充分解釋為什麼需要使用該工具。使用者查核不會用於公開連接使用者帳號使用的IP位址。' })
}]
});
work_area.append({ type: 'div', id: 'arvpreview', label: [ previewlink ] });
work_area.append({ type: 'div', id: 'twinklearv-previewbox', style: 'display: none' });
work_area.append({
type: 'div',
label: [
conv({ hans: '请使用常识决定是否以', hant: '請使用常識決定是否以' }),
$('<code>').addClass('tw-arv-sockmaster').attr('style', 'margin: 2px;')[0],
conv({ hans: '通知用户。这不是必须的,对于涉及新用户的报告而言,通知他们能让报告显得更公平,但是许多情况下(如长期破坏者)通知更可能适得其反。', hant: '通知使用者。這不是必須的,對於涉及新使用者的報告而言,通知他們能讓報告顯得更公平,但是許多情況下(如長期破壞者)通知更可能適得其反。' })
]
});
work_area = work_area.render();
$('input:text[name=sockpuppet]', work_area).first().val(root.uid.value);
old_area.parentNode.replaceChild(work_area, old_area);
root.spinoticepreviewer = new Morebits.wiki.preview($(work_area).find('#twinklearv-spinoticebox').last()[0]);
Twinkle.arv.callback.spi_notice(root, root.uid.value);
Twinkle.arv.callback.set_sockmaster(root.uid.value);
break;
}
root.previewer = new Morebits.wiki.preview($(work_area).find('#twinklearv-previewbox').last()[0]);
};
Twinkle.arv.callback.preview = function(form) {
var reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
var input = Morebits.quickForm.getInputData(form);
var title;
switch (input.category) {
case 'vip': title = 'Wikipedia:当前的破坏'; break;
case 'ewip': title = 'Wikipedia:管理员布告板/编辑争议'; break;
case 'username': title = 'Wikipedia:管理员布告板/不当用户名'; break;
case 'spi': title = 'Wikipedia:傀儡調查/案件/' + input.sockmaster; break;
default: title = mw.config.get('wgPageName'); break;
}
form.previewer.beginRender('__NOTOC__' + reason[0], title);
};
Twinkle.arv.callback.getReportWikitext = function(form) {
var input = Morebits.quickForm.getInputData(form);
var reason = '';
var comment = '';
var uid = input.uid;
var checkTitle = function(title, revid) {
if (/https?:\/\//.test(title)) {
alert(conv({ hans: '页面名称不能使用网址。', hant: '頁面名稱不能使用網址。' }));
return false;
}
var page;
try {
page = new mw.Title(title);
} catch (error) {
alert(conv({ hans: '“', hant: '「' }) + title + conv({ hans: '”不是一个有效的页面名称,如要使用差异链接请放在“评论”', hant: '」不是一個有效的頁面名稱,如要使用差異連結請放在「評論」' }) + (revid ? conv({ hans: ',或正确输入“修订版本”', hant: ',或正確輸入「修訂版本」' }) : '') + '。');
return false;
}
if (page.namespace === -1) {
alert(conv({ hans: '“', hant: '「' }) + title + conv({ hans: '”属于特殊页面,如要使用差异链接请放在“评论”', hant: '」屬於特殊頁面,如要使用差異連結請放在「評論」' }) + (revid ? conv({ hans: ',或正确输入“修订版本”', hant: ',或正確輸入「修訂版本」' }) : '') + '。');
return false;
}
return page;
};
var page;
switch (input.category) {
// Report user for vandalism
case 'aiv':
/* falls through */
default:
if (!input.arvtype.length && input.reason === '') {
alert(conv({ hans: '您必须指定理由', hant: '您必須指定理由' }));
return;
}
reason += '=== ' + (input.hidename ? conv({ hans: '已隐藏用户名', hant: '已隱藏使用者名稱' }) : uid) + ' ===\n';
reason += "* '''{{vandal|" + (/=/.test(uid) ? '1=' : '') + uid;
if (input.hidename) {
reason += '|hidename=1';
}
reason += "}}'''\n";
var types = input.arvtype.map(function(v) {
switch (v) {
case 'final':
return '已发出最后警告';
case 'postblock':
return '封禁过期后随即破坏';
case 'spambot':
return '显而易见的spambot或失窃账户';
case 'vandalonly':
return '显而易见的纯破坏用户';
case 'promoonly':
return '仅用来散发广告宣传的用户';
default:
return '未知理由';
}
}).join(',');
if (input.page !== '') {
page = checkTitle(input.page, true);
if (!page) {
return;
}
comment += '* {{pagelinks|' + (page.getPrefixedText().indexOf('=') > -1 ? '1=' : '') + page.getPrefixedText() + '}}';
if (input.badid) {
comment += '({{diff|' + page.getPrefixedText() + '|' + input.badid + '|' + (input.goodid ? input.goodid : '') + '|diff}})';
}
comment += '\n';
}
if (types) {
comment += '* ' + types;
}
if (input.reason !== '') {
input.reason = input.reason.replace(/\n\n+/g, '\n');
input.reason = input.reason.replace(/\r?\n/g, '\n*:'); // indent newlines
comment += (types ? '。' : '* ') + input.reason;
}
comment = comment.trim();
comment = Morebits.string.appendPunctuation(comment);
reason += comment + '\n* 发现人:~~~~\n* 处理:';
break;
// Report 3RR
case 'ewip':
if (input.reason === '') {
alert(conv({ hans: '您必须指定理由', hant: '您必須指定理由' }));
return;
}
reason += '=== ' + uid + ' ===\n';
reason += "* '''{{vandal|" + (/=/.test(uid) ? '1=' : '') + uid + "}}'''\n";
var pages = $.map($('input:text[name=page]', form), function (o) {
return $(o).val() || null;
});
for (var i = 0; i < pages.length; i++) {
page = checkTitle(pages[i], false);
if (!page) {
return;
}
comment += '* {{pagelinks|' + (page.getPrefixedText().indexOf('=') > -1 ? '1=' : '') + page.getPrefixedText() + '}}\n';
}
input.reason = input.reason.replace(/\n\n+/g, '\n');
input.reason = input.reason.replace(/\r?\n/g, '\n*:'); // indent newlines
comment += '* ' + input.reason + '\n';
comment = comment.trim();
comment = Morebits.string.appendPunctuation(comment);
reason += comment + '\n* 提報人:~~~~\n* 处理:';
break;
// Report inappropriate username
case 'username':
types = input.arvtype.map(Morebits.string.toLowerCaseFirstChar);
var hasShared = types.indexOf('shared') > -1;
if (hasShared) {
types.splice(types.indexOf('shared'), 1);
}
if (types.indexOf('侮辱性') !== -1) {
if (!confirm(conv({
hans: '警告:严重的侮辱性用户名和针对特定个人的侮辱性用户名不应在公开页面报告,而是应当私下联系监督员处理。是否继续?', hant:
'警告:嚴重的侮辱性使用者名稱和針對特定個人的侮辱性使用者名稱不應在公開頁面報告,而是應當私下聯絡監督員處理。是否繼續?'
}))) {
return;
}
}
if (types.length <= 2) {
types = types.join('和');
} else {
types = [ types.slice(0, -1).join('、'), types.slice(-1) ].join('和');
}
comment += '*{{user-uaa|1=' + uid;
if (input.hidename) {
comment += '|hidename=1';
}
comment += '}} – ';
if (types.length) {
comment += types + conv({ hans: '用户名', hant: '使用者名稱' });
}
if (types.length && hasShared) {
comment += ',';
}
if (hasShared) {
comment += conv({ hans: '暗示该账户并非由一人拥有', hant: '暗示該帳號並非由一人擁有' });
}
if (types.length || hasShared) {
comment += '。';
}
if (input.reason) {
comment += Morebits.string.toUpperCaseFirstChar(input.reason);
}
comment = Morebits.string.appendPunctuation(comment);
comment += '--~~~~';
comment = comment.replace(/\r?\n/g, '\n*:'); // indent newlines
reason = comment;
break;
// WP:SPI
case 'spi':
if (!input.reason) {
alert(conv({ hans: '请输入证据。', hant: '請輸入證據。' }));
return;
}
var sockpuppets = Morebits.array.uniq($.map($('input:text[name=sockpuppet]', form), function(o) {
return $(o).val().trim() || null;
}));
if (!sockpuppets[0]) {
alert(conv({ hans: '您没有指定任何傀儡。', hant: '您沒有指定任何傀儡。' }));
return;
}
comment += '{{subst:SPI report|';
if (sockpuppets.indexOf(input.sockmaster) === -1) {
comment += '1={{subst:#ifexist:{{subst:FULLPAGENAME}}||' + input.sockmaster + '}}|';
}
comment += sockpuppets.map(function(sock, index) {
return (index + 2) + '=' + sock;
}).join('|') + '\n|evidence=' + Morebits.string.appendPunctuation(input.reason) + '\n';
if (input.checkuser) {
comment += '|checkuser=yes';
}
comment += '}}';
reason = comment;
break;
}
return [reason, comment];
};
Twinkle.arv.callback.evaluate = function(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
var uid = input.uid;
var reason;
var summary;
switch (input.category) {
// Report user for vandalism
case 'aiv':
/* falls through */
default:
reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
summary = conv({ hans: '报告', hant: '報告' }) + '[[Special:Contributions/' + uid + '|' + uid + ']]';
if (input.hidename) {
summary = conv({ hans: '报告一名用户', hant: '報告一名使用者' });
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:当前的破坏';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var aivPage = new Morebits.wiki.page('Wikipedia:当前的破坏', conv({ hans: '处理VIP请求', hant: '處理VIP請求' }));
aivPage.setFollowRedirect(true);
aivPage.load(function() {
var text = aivPage.getPageText();
var $aivLink = '<a target="_blank" href="/wiki/WP:VIP">WP:VIP</a>';
// check if user has already been reported
if (new RegExp('===\\s*\\{\\{\\s*(?:[Vv]andal)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}\\s*===').test(text)) {
aivPage.getStatusElement().error(conv({ hans: '报告已存在,将不会加入新的', hant: '報告已存在,將不會加入新的' }));
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其加入到', hant: '您輸入的評論已在下方提供,您可以將其加入到' }) + $aivLink + conv({ hans: '已存在的小节中:', hant: '已存在的小節中:' }));
return;
}
aivPage.setPageSection(0);
aivPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
aivPage.setEditSummary(summary);
aivPage.setChangeTags(Twinkle.changeTags);
aivPage.setAppendText('\n' + reason[0]);
aivPage.append();
});
break;
// Report 3RR
case 'ewip':
reason = Twinkle.arv.callback.getReportWikitext(form);
if (reason === undefined) {
return;
}
summary = conv({ hans: '报告', hant: '報告' }) + '[[Special:Contributions/' + uid + '|' + uid + ']]';
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:管理员布告板/编辑争议';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var ewipPage = new Morebits.wiki.page('Wikipedia:管理员布告板/编辑争议', conv({ hans: '处理EWIP请求', hant: '處理EWIP請求' }));
ewipPage.setFollowRedirect(true);
ewipPage.load(function() {
var text = ewipPage.getPageText();
var $ewipLink = '<a target="_blank" href="/wiki/WP:EWIP">WP:EWIP</a>';
// check if user has already been reported
if (new RegExp('===\\s*\\{\\{\\s*(?:[Vv]andal)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}\\s*===').test(text)) {
ewipPage.getStatusElement().error(conv({ hans: '报告已存在,将不会加入新的', hant: '報告已存在,將不會加入新的' }));
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其加入到', hant: '您輸入的評論已在下方提供,您可以將其加入到' }) + $ewipLink + conv({ hans: '已存在的小节中:', hant: '已存在的小節中:' }));
return;
}
ewipPage.setPageSection(0);
ewipPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
ewipPage.setEditSummary(summary);
ewipPage.setChangeTags(Twinkle.changeTags);
ewipPage.setAppendText('\n' + reason[0]);
ewipPage.append();
});
break;
// Report inappropriate username
case 'username':
reason = Twinkle.arv.callback.getReportWikitext(form);
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = 'Wikipedia:管理员布告板/不当用户名';
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var uaaPage = new Morebits.wiki.page('Wikipedia:管理员布告板/不当用户名', conv({ hans: '处理UAA请求', hant: '處理UAA請求' }));
uaaPage.setFollowRedirect(true);
uaaPage.load(function() {
var text = uaaPage.getPageText();
// check if user has already been reported
if (new RegExp('\\{\\{\\s*user-uaa\\s*\\|\\s*(1\\s*=\\s*)?' + Morebits.string.escapeRegExp(uid) + '\\s*(\\||\\})').test(text)) {
uaaPage.getStatusElement().error(conv({ hans: '用户已被列入。', hant: '使用者已被列入。' }));
var $uaaLink = '<a target="_blank" href="/wiki/WP:UAA">WP:UAA</a>';
Morebits.status.printUserText(reason[1], conv({ hans: '您输入的评论已在下方提供,您可以将其手工加入', hant: '您輸入的評論已在下方提供,您可以將其手工加入' }) + $uaaLink + conv({ hans: '上该用户的报告中:', hant: '上該使用者的報告中:' }));
return;
}
uaaPage.getStatusElement().status(conv({ hans: '加入新报告…', hant: '加入新報告…' }));
uaaPage.setEditSummary(conv({ hans: '新提报', hant: '新提報' }));
uaaPage.setChangeTags(Twinkle.changeTags);
uaaPage.setAppendText('\n\n' + reason[0]);
uaaPage.append();
});
break;
// WP:SPI
case 'spi':
reason = Twinkle.arv.callback.getReportWikitext(form);
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var reportpage = 'Wikipedia:傀儡調查/案件/' + input.sockmaster;
Morebits.wiki.actionCompleted.redirect = reportpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '报告完成', hant: '報告完成' });
var spiPage = new Morebits.wiki.page(reportpage, conv({ hans: '抓取讨论页面', hant: '抓取討論頁面' }));
spiPage.setFollowRedirect(true);
spiPage.setEditSummary(conv({ hans: '加入新提报', hant: '加入新提報' }));
spiPage.setChangeTags(Twinkle.changeTags);
spiPage.setAppendText(reason[0]);
spiPage.setWatchlist(Twinkle.getPref('spiWatchReport'));
spiPage.append();
break;
}
};
Twinkle.addInitCallback(Twinkle.arv, 'arv');
})(jQuery);
// </nowiki>
f2d42199b9b3c6ccc713a10d99a13654c2695474
MediaWiki:Gadget-twinklewarn.js
8
152
307
306
2024-08-03T04:07:18Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklewarn.js: Warn module
****************************************
* Mode of invocation: Tab ("Warn")
* Active on: Any page with relevant user name (userspace, contribs,
* etc.), as well as the rollback success page
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.warn = function twinklewarn() {
if (Morebits.wiki.flow.relevantUserName()) {
Twinkle.addPortletLink(Twinkle.warn.callback, '警告', 'tw-warn', conv({ hans: '警告或提醒用户', hant: '警告或提醒使用者' }));
if (Twinkle.getPref('autoMenuAfterRollback') &&
mw.config.get('wgNamespaceNumber') === 3 &&
mw.util.getParamValue('vanarticle') &&
!mw.util.getParamValue('friendlywelcome') &&
!mw.util.getParamValue('noautowarn')) {
Twinkle.warn.callback();
}
}
// Modify URL of talk page on rollback success pages, makes use of a
// custom message box in [[MediaWiki:Rollback-success]]
if (mw.config.get('wgAction') === 'rollback') {
var $vandalTalkLink = $('#mw-rollback-success').find('.mw-usertoollinks a').first();
if ($vandalTalkLink.length) {
Twinkle.warn.makeVandalTalkLink($vandalTalkLink, Morebits.pageNameNorm);
$vandalTalkLink.css('font-weight', 'bold');
}
}
if (mw.config.get('wgCanonicalSpecialPageName') === 'AbuseLog' && mw.config.get('wgAbuseFilterVariables') !== null) {
var afTalkLink = $('.mw-usertoollinks-talk').first();
if (afTalkLink.length) {
Twinkle.warn.makeVandalTalkLink(afTalkLink, mw.config.get('wgAbuseFilterVariables').page_prefixedtitle);
afTalkLink.css('font-weight', 'bold');
}
}
// Override the mw.notify function to allow us to inject a link into the
// rollback success popup. Only users with the 'rollback' right need this,
// but we have no nice way of knowing who has that right (what with global
// groups and the like)
/*
else if( mw.config.get('wgAction') === 'history' ) {
mw.notifyOriginal = mw.notify;
mw.notify = function mwNotifyTwinkleOverride(message, options) {
// This is a horrible, awful hack to add a link to the rollback success
// popup. All other notification popups should be left untouched.
// It won't work for people whose user language is not English.
// As it's a hack, it's liable to stop working or break sometimes,
// particularly if the text or format of the confirmation message
// (MediaWiki:Rollback-success-notify) changes.
var regexMatch;
if ( options && options.title && mw.msg && options.title === mw.msg('actioncomplete') &&
message && $.isArray(message) && message[0] instanceof HTMLParagraphElement &&
(regexMatch = /^(?:回退|還原|取消|撤销|撤銷)(.+)(?:编辑|編輯|做出的編輯|做出的编辑|做出的修订版本|做出的修訂版本)/.exec(message[0].innerText))
) {
// Create a nicely-styled paragraph to place the link in
var $p = $('<p/>');
$p.css("margin", "0.5em -1.5em -1.5em");
$p.css("padding", "0.5em 1.5em 0.8em");
$p.css("border-top", "1px #666 solid");
$p.css("cursor", "default");
$p.click(function(e) { e.stopPropagation(); });
// Create the new talk link and append it to the end of the message
var $vandalTalkLink = $('<a/>');
$vandalTalkLink.text("用Twinkle警告用户");
//$vandalTalkLink.css("display", "block");
$vandalTalkLink.attr("href", mw.util.getUrl("User talk:" + regexMatch[1]));
Twinkle.warn.makeVandalTalkLink($vandalTalkLink);
$p.append($vandalTalkLink);
message[0].appendChild($p.get()[0]);
// Don't auto-hide the notification. It only stays around for 5 seconds by
// default, which might not be enough time for the user to read it and
// click the link
options.autoHide = false;
}
mw.notifyOriginal.apply(mw, arguments);
};
}
*/
// for testing, use:
// mw.notify([ $("<p>Reverted edits by foo; changed</p>")[0] ], { title: mw.msg('actioncomplete') } );
};
Twinkle.warn.makeVandalTalkLink = function($vandalTalkLink, pagename) {
$vandalTalkLink.wrapInner($('<span/>').attr('title', conv({ hans: '如果合适,您可以用Twinkle在该用户讨论页上做出警告。', hant: '如果合適,您可以用Twinkle在該使用者討論頁上做出警告。' })));
var extraParam = 'vanarticle=' + mw.util.rawurlencode(pagename);
var href = $vandalTalkLink.attr('href');
if (href.indexOf('?') === -1) {
$vandalTalkLink.attr('href', href + '?' + extraParam);
} else {
$vandalTalkLink.attr('href', href + '&' + extraParam);
}
};
// Used to close window when switching to ARV in autolevel
Twinkle.warn.dialog = null;
Twinkle.warn.callback = function twinklewarnCallback() {
if (Morebits.wiki.flow.relevantUserName() === mw.config.get('wgUserName') &&
!confirm(conv({ hans: '您将要警告自己!您确定要继续吗?', hant: '您將要警告自己!您確定要繼續嗎?' }))) {
return;
}
var dialog;
Twinkle.warn.dialog = new Morebits.simpleWindow(600, 440);
dialog = Twinkle.warn.dialog;
dialog.setTitle(conv({ hans: '警告、提醒用户', hant: '警告、提醒使用者' }));
dialog.setScriptName('Twinkle');
dialog.addFooterLink(conv({ hans: '选择警告级别', hant: '選擇警告級別' }), 'WP:WARN');
dialog.addFooterLink(conv({ hans: '警告设置', hant: '警告設定' }), 'WP:TW/PREF#warn');
dialog.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#warn');
var form = new Morebits.quickForm(Twinkle.warn.callback.evaluate);
var main_select = form.append({
type: 'field',
label: conv({ hans: '选择要发送的警告或提醒类型', hant: '選擇要傳送的警告或提醒類別' }),
tooltip: conv({ hans: '首先选择一组,再选择具体的警告模板。', hant: '首先選擇一組,再選擇具體的警告模板。' })
});
var main_group = main_select.append({
type: 'select',
name: 'main_group',
tooltip: conv({ hans: '您可在Twinkle参数设置中设置默认选择的选项', hant: '您可在Twinkle偏好設定中設定預設選擇的選項' }),
event: Twinkle.warn.callback.change_category
});
var defaultGroup = parseInt(Twinkle.getPref('defaultWarningGroup'), 10);
main_group.append({ type: 'option', label: conv({ hans: '自动选择层级(1-4)', hant: '自動選擇層級(1-4)' }), value: 'autolevel', selected: defaultGroup === 11 });
main_group.append({ type: 'option', label: '1:提醒', value: 'level1', selected: defaultGroup === 1 });
main_group.append({ type: 'option', label: '2:注意', value: 'level2', selected: defaultGroup === 2 });
main_group.append({ type: 'option', label: '3:警告', value: 'level3', selected: defaultGroup === 3 });
main_group.append({ type: 'option', label: conv({ hans: '4:最后警告', hant: '4:最後警告' }), value: 'level4', selected: defaultGroup === 4 });
main_group.append({ type: 'option', label: '4im:唯一警告', value: 'level4im', selected: defaultGroup === 5 });
if (Twinkle.getPref('combinedSingletMenus')) {
main_group.append({ type: 'option', label: conv({ hans: '单层级消息', hant: '單層級訊息' }), value: 'singlecombined', selected: defaultGroup === 6 || defaultGroup === 7 });
} else {
main_group.append({ type: 'option', label: conv({ hans: '单层级提醒', hant: '單層級提醒' }), value: 'singlenotice', selected: defaultGroup === 6 });
main_group.append({ type: 'option', label: conv({ hans: '单层级警告', hant: '單層級警告' }), value: 'singlewarn', selected: defaultGroup === 7 });
}
if (Twinkle.getPref('customWarningList').length) {
main_group.append({ type: 'option', label: conv({ hans: '自定义警告', hant: '自訂警告' }), value: 'custom', selected: defaultGroup === 9 });
}
main_group.append({ type: 'option', label: '所有警告模板', value: 'kitchensink', selected: defaultGroup === 10 });
main_select.append({ type: 'select', name: 'sub_group', event: Twinkle.warn.callback.change_subcategory }); // Will be empty to begin with.
form.append({
type: 'input',
name: 'article',
label: conv({ hans: '页面链接', hant: '頁面連結' }),
value: mw.util.getParamValue('vanarticle') || '',
size: 50,
tooltip: conv({ hans: '给模板中加入一页面链接,可留空。', hant: '給模板中加入一頁面連結,可留空。' }),
placeholder: conv({ hans: '仅限一个,勿使用网址、[[ ]],可使用Special:Diff', hant: '僅限一個,勿使用網址、[[ ]],可使用Special:Diff' })
});
form.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-warn-warning-messages'
});
var more = form.append({ type: 'field', name: 'reasonGroup', label: conv({ hans: '警告信息', hant: '警告資訊' }) });
more.append({ type: 'textarea', label: conv({ hans: '可选信息:', hant: '可選資訊:' }), name: 'reason', tooltip: conv({ hans: '理由或是附加信息', hant: '理由或是附加資訊' }) });
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.warn.callbacks.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
more.append({ type: 'div', id: 'warningpreview', label: [ previewlink ] });
more.append({ type: 'div', id: 'twinklewarn-previewbox', style: 'display: none' });
more.append({ type: 'submit', label: '提交' });
var result = form.render();
dialog.setContent(result);
dialog.display();
result.main_group.root = result;
result.previewer = new Morebits.wiki.preview($(result).find('div#twinklewarn-previewbox').last()[0]);
// Potential notices for staleness and missed reverts
var message = '';
var query = {};
var vanrevid = mw.util.getParamValue('vanarticlerevid');
if (vanrevid) {
// If you tried reverting, check if *you* actually reverted
if (!mw.util.getParamValue('noautowarn') && mw.util.getParamValue('vanarticle')) { // Via fluff link
query = {
action: 'query',
titles: mw.util.getParamValue('vanarticle'),
prop: 'revisions',
rvstartid: vanrevid,
rvlimit: 2,
rvdir: 'newer',
rvprop: 'user'
};
new Morebits.wiki.api(conv({ hans: '检查您是否成功回退该页面', hant: '檢查您是否成功回退該頁面' }), query, function (apiobj) {
var revertUser = $(apiobj.getResponse()).find('revisions rev')[1].getAttribute('user');
if (revertUser && revertUser !== mw.config.get('wgUserName')) {
message += conv({ hans: '其他人回退了该页面,并可能已经警告该用户。', hant: '其他人回退了該頁面,並可能已經警告該使用者。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}).post();
}
// Confirm edit wasn't too old for a warning
var checkStale = function(vantimestamp) {
var revDate = new Morebits.date(vantimestamp);
if (vantimestamp && revDate.isValid()) {
if (revDate.add(24, 'hours').isBefore(new Date())) {
message += conv({ hans: '这笔编辑是在24小时前做出的,现在警告可能已过时。', hant: '這筆編輯是在24小時前做出的,現在警告可能已過時。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}
};
var vantimestamp = mw.util.getParamValue('vantimestamp');
// Provided from a fluff module-based revert, no API lookup necessary
if (vantimestamp) {
checkStale(vantimestamp);
} else {
query = {
action: 'query',
prop: 'revisions',
rvprop: 'timestamp',
revids: vanrevid
};
new Morebits.wiki.api(conv({ hans: '获取版本时间戳', hant: '取得版本時間戳' }), query, function (apiobj) {
vantimestamp = $(apiobj.getResponse()).find('revisions rev').attr('timestamp');
checkStale(vantimestamp);
}).post();
}
}
if (mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName())) {
query = {
format: 'json',
action: 'query',
list: 'usercontribs',
uclimit: 1,
ucend: new Morebits.date().subtract(30, 'days').format('YYYY-MM-DDTHH:MM:ssZ', 'utc'),
ucuser: Morebits.wiki.flow.relevantUserName()
};
new Morebits.wiki.api(conv({ hans: '检查该IP用户上一笔贡献时间', hant: '檢查該IP使用者上一筆貢獻時間' }), query, function (apiobj) {
if (apiobj.getResponse().query.usercontribs.length === 0) {
message += conv({ hans: '此IP用户上一次编辑在30日之前,现在警告可能已过时。', hant: '此IP使用者上一次編輯在30日之前,現在警告可能已過時。' });
$('#twinkle-warn-warning-messages').text('注意:' + message);
}
}).post();
}
var init = function() {
// We must init the first choice (General Note);
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.main_group.dispatchEvent(evt);
};
Morebits.wiki.flow.check('User_talk:' + Morebits.wiki.flow.relevantUserName(), function () {
Twinkle.warn.isFlow = true;
init();
}, function () {
Twinkle.warn.isFlow = false;
init();
});
};
// This is all the messages that might be dispatched by the code
// Each of the individual templates require the following information:
// label (required): A short description displayed in the dialog
// summary (required): The edit summary used. If an article name is entered, the summary is postfixed with "on [[article]]", and it is always postfixed with ". $summaryAd"
// suppressArticleInSummary (optional): Set to true to suppress showing the article name in the edit summary. Useful if the warning relates to attack pages, or some such.
Twinkle.warn.messages = {
levels: [{
category: conv({ hans: '不同类型的非建设编辑', hant: '不同類別的非建設編輯' }),
list: {
'uw-vandalism': {
level1: {
label: conv({ hans: '明显的破坏', hant: '明顯的破壞' }),
summary: conv({ hans: '提醒:明显破坏', hant: '提醒:明顯破壞' })
},
level2: {
label: conv({ hans: '明显的破坏', hant: '明顯的破壞' }),
summary: conv({ hans: '注意:明显破坏', hant: '注意:明顯破壞' })
},
level3: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '警告:恶意破坏', hant: '警告:惡意破壞' })
},
level4: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '最后警告:恶意破坏', hant: '最後警告:惡意破壞' })
},
level4im: {
label: conv({ hans: '恶意破坏', hant: '惡意破壞' }),
summary: conv({ hans: '唯一警告:恶意破坏', hant: '唯一警告:惡意破壞' })
}
},
'uw-test': {
level1: {
label: conv({ hans: '进行编辑测试而未及时清理', hant: '進行編輯測試而未及時清理' }),
summary: conv({ hans: '提醒:进行编辑测试而未及时清理', hant: '提醒:進行編輯測試而未及時清理' })
},
level2: {
label: conv({ hans: '进行损毁性的编辑测试', hant: '進行損毀性的編輯測試' }),
summary: conv({ hans: '注意:进行编辑测试', hant: '注意:進行編輯測試' })
},
level3: {
label: conv({ hans: '编辑测试', hant: '編輯測試' }),
summary: conv({ hans: '警告:编辑测试', hant: '警告:編輯測試' })
},
level4: {
label: conv({ hans: '编辑测试', hant: '編輯測試' }),
summary: conv({ hans: '最后警告:编辑测试', hant: '最後警告:編輯測試' })
}
},
'uw-delete': {
level1: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '提醒:不恰当地移除页面内容、模板或资料', hant: '提醒:不恰當地移除頁面內容、模板或資料' })
},
level2: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '注意:不恰当地移除页面内容、模板或资料', hant: '注意:不恰當地移除頁面內容、模板或資料' })
},
level3: {
label: conv({ hans: '不恰当地移除页面内容、模板或资料', hant: '不恰當地移除頁面內容、模板或資料' }),
summary: conv({ hans: '警告:不恰当地移除页面内容、模板或资料', hant: '警告:不恰當地移除頁面內容、模板或資料' })
},
level4: {
label: conv({ hans: '移除页面、移除内容或模板', hant: '移除頁面、移除內容或模板' }),
summary: conv({ hans: '最后警告:移除页面、移除内容或模板', hant: '最後警告:移除頁面、移除內容或模板' })
},
level4im: {
label: conv({ hans: '移除页面内容、模板或资料', hant: '移除頁面內容、模板或資料' }),
summary: conv({ hans: '唯一警告:移除页面内容、模板或资料', hant: '唯一警告:移除頁面內容、模板或資料' })
}
},
'uw-redirect': {
level1: {
label: conv({ hans: '创建破坏性的重定向', hant: '建立破壞性的重定向' }),
summary: conv({ hans: '提醒:创建破坏性的重定向', hant: '提醒:建立破壞性的重定向' })
},
level2: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '注意:创建恶意重定向', hant: '注意:建立惡意重定向' })
},
level3: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '警告:创建恶意重定向', hant: '警告:建立惡意重定向' })
},
level4: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '最后警告:创建恶意重定向', hant: '最後警告:建立惡意重定向' })
},
level4im: {
label: conv({ hans: '创建恶意重定向', hant: '建立惡意重定向' }),
summary: conv({ hans: '唯一警告:创建恶意重定向', hant: '唯一警告:建立惡意重定向' })
}
},
'uw-tdel': {
level1: {
label: conv({ hans: '在问题仍未解决的情况下移除维护性模板', hant: '在問題仍未解決的情況下移除維護性模板' }),
summary: conv({ hans: '提醒:移除维护性模板', hant: '提醒:移除維護性模板' })
},
level2: {
label: conv({ hans: '在问题仍未解决的情况下移除维护性模板', hant: '在問題仍未解決的情況下移除維護性模板' }),
summary: conv({ hans: '注意:移除维护性模板', hant: '注意:移除維護性模板' })
},
level3: {
label: conv({ hans: '移除维护性模板', hant: '移除維護性模板' }),
summary: conv({ hans: '警告:移除维护性模板', hant: '警告:移除維護性模板' })
},
level4: {
label: conv({ hans: '移除维护性模板', hant: '移除維護性模板' }),
summary: conv({ hans: '最后警告:移除维护性模板', hant: '最後警告:移除維護性模板' })
}
},
'uw-joke': {
level1: {
label: conv({ hans: '在百科全书内容中加入玩笑', hant: '在百科全書內容中加入玩笑' }),
summary: conv({ hans: '提醒:加入不当玩笑', hant: '提醒:加入不當玩笑' })
},
level2: {
label: conv({ hans: '在百科全书内容中加入玩笑', hant: '在百科全書內容中加入玩笑' }),
summary: conv({ hans: '注意:加入不当玩笑', hant: '注意:加入不當玩笑' })
},
level3: {
label: conv({ hans: '在百科全书内容中加入不当玩笑', hant: '在百科全書內容中加入不當玩笑' }),
summary: conv({ hans: '警告:在百科全书内容中加入不当玩笑', hant: '警告:在百科全書內容中加入不當玩笑' })
},
level4: {
label: conv({ hans: '在百科全书内容中加入不当玩笑', hant: '在百科全書內容中加入不當玩笑' }),
summary: conv({ hans: '最后警告:在百科全书内容中加入不当玩笑', hant: '最後警告:在百科全書內容中加入不當玩笑' })
},
level4im: {
label: conv({ hans: '加入不当玩笑', hant: '加入不當玩笑' }),
summary: conv({ hans: '唯一警告:加入不当玩笑', hant: '唯一警告:加入不當玩笑' })
}
},
'uw-create': {
level1: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '提醒:创建不当页面', hant: '提醒:建立不當頁面' })
},
level2: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '注意:创建不当页面', hant: '注意:建立不當頁面' })
},
level3: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '警告:创建不当页面', hant: '警告:建立不當頁面' })
},
level4: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '最后警告:创建不当页面', hant: '最後警告:建立不當頁面' })
},
level4im: {
label: conv({ hans: '创建不当页面', hant: '建立不當頁面' }),
summary: conv({ hans: '唯一警告:创建不当页面', hant: '唯一警告:建立不當頁面' })
}
},
'uw-upload': {
level1: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '提醒:上传不当图像', hant: '提醒:上傳不當圖像' })
},
level2: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '注意:上传不当图像', hant: '注意:上傳不當圖像' })
},
level3: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '警告:上传不当图像', hant: '警告:上傳不當圖像' })
},
level4: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '最后警告:上传不当图像', hant: '最後警告:上傳不當圖像' })
},
level4im: {
label: conv({ hans: '上传不当图像', hant: '上傳不當圖像' }),
summary: conv({ hans: '唯一警告:上传不当图像', hant: '唯一警告:上傳不當圖像' })
}
},
'uw-image': {
level1: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '提醒:在页面中加入不当图片', hant: '提醒:在頁面中加入不當圖片' })
},
level2: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '注意:在页面中加入不当图片', hant: '注意:在頁面中加入不當圖片' })
},
level3: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '警告:在页面中加入不当图片', hant: '警告:在頁面中加入不當圖片' })
},
level4: {
label: conv({ hans: '在页面中加入不当图片', hant: '在頁面中加入不當圖片' }),
summary: conv({ hans: '最后警告:在页面中加入不当图片', hant: '最後警告:在頁面中加入不當圖片' })
},
level4im: {
label: conv({ hans: '加入不恰当的图片', hant: '加入不恰當的圖片' }),
summary: conv({ hans: '唯一警告:加入不恰当的图片', hant: '唯一警告:加入不恰當的圖片' })
}
},
'uw-nor': {
level1: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '提醒:在条目中加入原创研究', hant: '提醒:在條目中加入原創研究' })
},
level2: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '注意:在条目中加入原创研究', hant: '注意:在條目中加入原創研究' })
},
level3: {
label: conv({ hans: '在条目中加入原创研究', hant: '在條目中加入原創研究' }),
summary: conv({ hans: '警告:在条目中加入原创研究', hant: '警告:在條目中加入原創研究' })
}
},
'uw-politicalbias': {
level1: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '提醒:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '提醒:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level2: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '注意:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '注意:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level3: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level4: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '最后警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '最後警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
},
level4im: {
label: conv({ hans: '违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '違反兩岸四地用語、朝鮮半島用語等相關規定' }),
summary: conv({ hans: '唯一警告:违反两岸四地用语、朝鲜半岛用语等相关规定', hant: '唯一警告:違反兩岸四地用語、朝鮮半島用語等相關規定' })
}
}
}
},
{
category: conv({ hans: '增加商品或政治广告', hant: '增加商品或政治廣告' }),
list: {
'uw-spam': {
level1: {
label: conv({ hans: '增加不合适的外部链接', hant: '增加不合適的外部連結' }),
summary: conv({ hans: '提醒:增加不合适的外部链接', hant: '提醒:增加不合適的外部連結' })
},
level2: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '注意:增加垃圾链接', hant: '注意:增加垃圾連結' })
},
level3: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '警告:增加垃圾链接', hant: '警告:增加垃圾連結' })
},
level4: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '最后警告:增加垃圾链接', hant: '最後警告:增加垃圾連結' })
},
level4im: {
label: conv({ hans: '增加垃圾链接', hant: '增加垃圾連結' }),
summary: conv({ hans: '唯一警告:增加垃圾链接', hant: '唯一警告:增加垃圾連結' })
}
},
'uw-advert': {
level1: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '提醒:利用维基百科来发布广告或推广', hant: '提醒:利用維基百科來發布廣告或推廣' })
},
level2: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '注意:利用维基百科来发布广告或推广', hant: '注意:利用維基百科來發布廣告或推廣' })
},
level3: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '警告:利用维基百科来发布广告或推广', hant: '警告:利用維基百科來發布廣告或推廣' })
},
level4: {
label: conv({ hans: '利用维基百科来发布广告或推广', hant: '利用維基百科來發布廣告或推廣' }),
summary: conv({ hans: '最后警告:利用维基百科来发布广告或推广', hant: '最後警告:利用維基百科來發布廣告或推廣' })
}
},
'uw-npov': {
level1: {
label: conv({ hans: '不遵守中立的观点方针', hant: '不遵守中立的觀點方針' }),
summary: conv({ hans: '提醒:不遵守中立的观点方针', hant: '提醒:不遵守中立的觀點方針' })
},
level2: {
label: conv({ hans: '不遵守中立的观点方针', hant: '不遵守中立的觀點方針' }),
summary: conv({ hans: '注意:不遵守中立的观点方针', hant: '注意:不遵守中立的觀點方針' })
},
level3: {
label: conv({ hans: '违反中立的观点方针', hant: '違反中立的觀點方針' }),
summary: conv({ hans: '警告:违反中立的观点方针', hant: '警告:違反中立的觀點方針' })
},
level4: {
label: conv({ hans: '违反中立的观点方针', hant: '違反中立的觀點方針' }),
summary: conv({ hans: '最后警告:违反中立的观点方针', hant: '最後警告:違反中立的觀點方針' })
}
}
}
},
{
category: conv({ hans: '加插不实及/或诽谤文字', hant: '加插不實及/或誹謗文字' }),
list: {
'uw-unsourced': {
level1: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '提醒:加入没有可靠来源佐证的内容', hant: '提醒:加入沒有可靠來源佐證的內容' })
},
level2: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '注意:加入没有可靠来源佐证的内容', hant: '注意:加入沒有可靠來源佐證的內容' })
},
level3: {
label: conv({ hans: '加入没有可靠来源佐证的内容', hant: '加入沒有可靠來源佐證的內容' }),
summary: conv({ hans: '警告:加入没有可靠来源佐证的内容', hant: '警告:加入沒有可靠來源佐證的內容' })
}
},
'uw-error': {
level1: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '提醒:故意加入不实内容', hant: '提醒:故意加入不實內容' })
},
level2: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '注意:故意加入不实内容', hant: '注意:故意加入不實內容' })
},
level3: {
label: conv({ hans: '故意加入不实内容', hant: '故意加入不實內容' }),
summary: conv({ hans: '警告:故意加入不实内容', hant: '警告:故意加入不實內容' })
}
},
'uw-biog': {
level1: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' }),
summary: conv({ hans: '提醒:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '提醒:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level2: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' }),
summary: conv({ hans: '注意:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '注意:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level3: {
label: conv({ hans: '在生者传记中加入没有可靠来源佐证而且带有争议的内容', hant: '在生者傳記中加入沒有可靠來源佐證而且帶有爭議的內容' }),
summary: conv({ hans: '警告:在生者传记中加入没有可靠来源佐证而且可能引发争议的内容', hant: '警告:在生者傳記中加入沒有可靠來源佐證而且可能引發爭議的內容' })
},
level4: {
label: conv({ hans: '加入有关在生人物而又缺乏来源的资料', hant: '加入有關在生人物而又缺乏來源的資料' }),
summary: conv({ hans: '最后警告:加入有关在生人物而又缺乏来源的资料', hant: '最後警告:加入有關在生人物而又缺乏來源的資料' })
},
level4im: {
label: conv({ hans: '加入有关在生人物而又缺乏来源的资料', hant: '加入有關在生人物而又缺乏來源的資料' }),
summary: conv({ hans: '唯一警告:加入有关在生人物而又缺乏来源的资料', hant: '唯一警告:加入有關在生人物而又缺乏來源的資料' })
}
},
'uw-defamatory': {
level1: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '提醒:加入诽谤内容', hant: '提醒:加入誹謗內容' })
},
level2: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '注意:加入诽谤内容', hant: '注意:加入誹謗內容' })
},
level3: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '警告:加入诽谤内容', hant: '警告:加入誹謗內容' })
},
level4: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '最后警告:加入诽谤内容', hant: '最後警告:加入誹謗內容' })
},
level4im: {
label: conv({ hans: '加入诽谤内容', hant: '加入誹謗內容' }),
summary: conv({ hans: '唯一警告:加入诽谤内容', hant: '唯一警告:加入誹謗內容' })
}
}
}
},
{
category: conv({ hans: '翻译品质', hant: '翻譯品質' }),
list: {
'uw-roughtranslation': {
level1: {
label: conv({ hans: '您翻译的质量有待改善', hant: '您翻譯的質量有待改善' }),
summary: conv({ hans: '提醒:您翻译的质量有待改善', hant: '提醒:您翻譯的質量有待改善' })
},
level2: {
label: conv({ hans: '粗劣翻译', hant: '粗劣翻譯' }),
summary: conv({ hans: '注意:粗劣翻译', hant: '注意:粗劣翻譯' })
},
level3: {
label: conv({ hans: '粗劣翻译', hant: '粗劣翻譯' }),
summary: conv({ hans: '警告:粗劣翻译', hant: '警告:粗劣翻譯' })
}
}
}
},
{
category: conv({ hans: '非能接受且违反方针或指引的单方面行为或操作', hant: '非能接受且違反方針或指引的單方面行為或操作' }),
list: {
'uw-notcensored': {
level1: {
label: conv({ hans: '因为“内容使人反感”而删除条目内容', hant: '因為「內容使人反感」而刪除條目內容' }),
summary: conv({ hans: '提醒:审查条目内容', hant: '提醒:審查條目內容' })
},
level2: {
label: conv({ hans: '内容审查', hant: '內容審查' }),
summary: conv({ hans: '注意:内容审查', hant: '注意:內容審查' })
},
level3: {
label: conv({ hans: '审查内容', hant: '審查內容' }),
summary: conv({ hans: '警告:审查内容', hant: '警告:審查內容' })
}
},
'uw-mos': {
level1: {
label: conv({ hans: '不恰当的条目格式、日期、语言等', hant: '不恰當的條目格式、日期、語言等' }),
summary: conv({ hans: '提醒:不恰当的条目格式、日期、语言等', hant: '提醒:不恰當的條目格式、日期、語言等' })
},
level2: {
label: conv({ hans: '不恰当的条目格式、日期、语言等', hant: '不恰當的條目格式、日期、語言等' }),
summary: conv({ hans: '注意:不恰当的条目格式、日期、语言等', hant: '注意:不恰當的條目格式、日期、語言等' })
},
level3: {
label: conv({ hans: '违反格式、日期、语言等规定', hant: '違反格式、日期、語言等規定' }),
summary: conv({ hans: '警告:违反格式、日期、语言等规定', hant: '警告:違反格式、日期、語言等規定' })
},
level4: {
label: conv({ hans: '违反格式、日期、语言等相关规定', hant: '違反格式、日期、語言等相關規定' }),
summary: conv({ hans: '最后警告:违反格式、日期、语言等相关规定', hant: '最後警告:違反格式、日期、語言等相關規定' })
}
},
'uw-move': {
level1: {
label: conv({ hans: '无故移动条目/新名称不符合命名规范', hant: '無故移動條目/新名稱不符合命名規範' }),
summary: conv({ hans: '提醒:不恰当地移动页面', hant: '提醒:不恰當地移動頁面' })
},
level2: {
label: conv({ hans: '把页面移动到不恰当、违反命名常规或违反共识的标题', hant: '把頁面移動到不恰當、違反命名常規或違反共識的標題' }),
summary: conv({ hans: '注意:不恰当地移动页面', hant: '注意:不恰當地移動頁面' })
},
level3: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '警告:不恰当地移动页面', hant: '警告:不恰當地移動頁面' })
},
level4: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '最后警告:不恰当地移动页面', hant: '最後警告:不恰當地移動頁面' })
},
level4im: {
label: conv({ hans: '不恰当地移动页面', hant: '不恰當地移動頁面' }),
summary: conv({ hans: '唯一警告:不恰当地移动页面', hant: '唯一警告:不恰當地移動頁面' })
}
},
'uw-cd': {
level1: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '提醒:清空讨论页', hant: '提醒:清空討論頁' })
},
level2: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '注意:清空讨论页', hant: '注意:清空討論頁' })
},
level3: {
label: conv({ hans: '清空讨论页', hant: '清空討論頁' }),
summary: conv({ hans: '警告:清空讨论页', hant: '警告:清空討論頁' })
}
},
'uw-chat': {
level1: {
label: conv({ hans: '在讨论页发表与改善条目无关的内容', hant: '在討論頁發表與改善條目無關的內容' }),
summary: conv({ hans: '提醒:在讨论页发表与改善条目无关的内容', hant: '提醒:在討論頁發表與改善條目無關的內容' })
},
level2: {
label: conv({ hans: '在讨论页发表与改善条目无关的内容', hant: '在討論頁發表與改善條目無關的內容' }),
summary: conv({ hans: '注意:在讨论页发表与改善条目无关的内容', hant: '注意:在討論頁發表與改善條目無關的內容' })
},
level3: {
label: conv({ hans: '在讨论页发表无关内容', hant: '在討論頁發表無關內容' }),
summary: conv({ hans: '警告:在讨论页发表无关内容', hant: '警告:在討論頁發表無關內容' })
},
level4: {
label: conv({ hans: '在讨论页进行不当讨论', hant: '在討論頁進行不當討論' }),
summary: conv({ hans: '最后警告:在讨论页进行不当讨论', hant: '最後警告:在討論頁進行不當討論' })
}
},
'uw-tpv': {
level1: {
label: '修改他人留言',
summary: '提醒:修改他人留言'
},
level2: {
label: '修改他人留言',
summary: '注意:修改他人留言'
},
level3: {
label: '修改他人留言',
summary: '警告:修改他人留言'
}
},
'uw-afd': {
level1: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '提醒:移除{{afd}}(页面存废讨论)模板', hant: '提醒:移除{{afd}}(頁面存廢討論)模板' })
},
level2: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '注意:移除{{afd}}(页面存废讨论)模板', hant: '注意:移除{{afd}}(頁面存廢討論)模板' })
},
level3: {
label: conv({ hans: '移除{{afd}}(页面存废讨论)模板', hant: '移除{{afd}}(頁面存廢討論)模板' }),
summary: conv({ hans: '警告:移除{{afd}}(页面存废讨论)模板', hant: '警告:移除{{afd}}(頁面存廢討論)模板' })
},
level4: {
label: '移除{{afd}}模板',
summary: conv({ hans: '最后警告:移除{{afd}}模板', hant: '最後警告:移除{{afd}}模板' })
}
},
'uw-speedy': {
level1: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '提醒:移除{{delete}}(快速删除)模板', hant: '提醒:移除{{delete}}(快速刪除)模板' })
},
level2: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '注意:移除{{delete}}(快速删除)模板', hant: '注意:移除{{delete}}(快速刪除)模板' })
},
level3: {
label: conv({ hans: '移除{{delete}}(快速删除)模板', hant: '移除{{delete}}(快速刪除)模板' }),
summary: conv({ hans: '警告:移除{{delete}}(快速删除)模板', hant: '警告:移除{{delete}}(快速刪除)模板' })
},
level4: {
label: '移除{{delete}}模板',
summary: conv({ hans: '最后警告:移除{{delete}}模板', hant: '最後警告:移除{{delete}}模板' })
}
}
}
},
{
category: conv({ hans: '对其他用户和条目的态度', hant: '對其他用戶和條目的態度' }),
list: {
'uw-npa': {
level1: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '提醒:针对用户的人身攻击', hant: '提醒:針對用戶的人身攻擊' })
},
level2: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '注意:针对用户的人身攻击', hant: '注意:針對用戶的人身攻擊' })
},
level3: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '警告:针对用户的人身攻击', hant: '警告:針對用戶的人身攻擊' })
},
level4: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '最后警告:针对用户的人身攻击', hant: '最後警告:針對用戶的人身攻擊' })
},
level4im: {
label: conv({ hans: '针对用户的人身攻击', hant: '針對用戶的人身攻擊' }),
summary: conv({ hans: '唯一警告:针对用户的人身攻击', hant: '唯一警告:針對用戶的人身攻擊' })
}
},
'uw-agf': {
level1: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '提醒:没有假定善意', hant: '提醒:沒有假定善意' })
},
level2: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '注意:没有假定善意', hant: '注意:沒有假定善意' })
},
level3: {
label: conv({ hans: '没有假定善意', hant: '沒有假定善意' }),
summary: conv({ hans: '警告:没有假定善意', hant: '警告:沒有假定善意' })
}
},
'uw-own': {
level1: {
label: conv({ hans: '主张条目所有权', hant: '主張條目所有權' }),
summary: conv({ hans: '提醒:主张条目所有权', hant: '提醒:主張條目所有權' })
},
level2: {
label: conv({ hans: '主张条目的所有权', hant: '主張條目的所有權' }),
summary: conv({ hans: '注意:主张条目的所有权', hant: '注意:主張條目的所有權' })
},
level3: {
label: conv({ hans: '主张条目的所有权', hant: '主張條目的所有權' }),
summary: conv({ hans: '警告:主张条目的所有权', hant: '警告:主張條目的所有權' })
}
},
'uw-tempabuse': {
level1: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '提醒:不当使用警告或封禁模板', hant: '提醒:不當使用警告或封禁模板' })
},
level2: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '注意:不当使用警告或封禁模板', hant: '注意:不當使用警告或封禁模板' })
},
level3: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '警告:不当使用警告或封禁模板', hant: '警告:不當使用警告或封禁模板' })
},
level4: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '最后警告:不当使用警告或封禁模板', hant: '最後警告:不當使用警告或封禁模板' })
},
level4im: {
label: conv({ hans: '不当使用警告或封禁模板', hant: '不當使用警告或封禁模板' }),
summary: conv({ hans: '唯一警告:不当使用警告或封禁模板', hant: '唯一警告:不當使用警告或封禁模板' })
}
}
}
}],
singlenotice: {
'uw-2redirect': {
label: conv({ hans: '在移动页面后应该修复双重重定向', hant: '在移動頁面後應該修復雙重重定向' }),
summary: conv({ hans: '提醒:在移动页面后应该修复双重重定向', hant: '提醒:在移動頁面後應該修復雙重重定向' })
},
'uw-aiv': {
label: conv({ hans: '举报的并不是破坏者,或者举报破坏前未进行警告', hant: '舉報的並不是破壞者,或者舉報破壞前未進行警告' }),
summary: conv({ hans: '提醒:不恰当地举报破坏', hant: '提醒:不恰當地舉報破壞' })
},
'uw-articlesig': {
label: conv({ hans: '在条目中签名', hant: '在條目中簽名' }),
summary: conv({ hans: '提醒:在条目中签名', hant: '提醒:在條目中簽名' })
},
'uw-autobiography': {
label: conv({ hans: '创建自传', hant: '建立自傳' }),
summary: conv({ hans: '提醒:创建自传', hant: '提醒:建立自傳' })
},
'uw-badcat': {
label: conv({ hans: '加入错误的页面分类', hant: '加入錯誤的頁面分類' }),
summary: conv({ hans: '提醒:加入错误的页面分类', hant: '提醒:加入錯誤的頁面分類' })
},
'uw-bite': {
label: conv({ hans: '伤害新手', hant: '傷害新手' }),
summary: conv({ hans: '提醒:伤害新手', hant: '提醒:傷害新手' })
},
'uw-booktitle': {
label: conv({ hans: '没有使用书名号来标示书籍、电影、音乐专辑等', hant: '沒有使用書名號來標示書籍、電影、音樂專輯等' }),
summary: conv({ hans: '提醒:没有使用书名号来标示书籍、电影、音乐专辑等', hant: '提醒:沒有使用書名號來標示書籍、電影、音樂專輯等' })
},
'uw-c&pmove': {
label: conv({ hans: '剪贴移动', hant: '剪貼移動' }),
summary: conv({ hans: '提醒:剪贴移动', hant: '提醒:剪貼移動' })
},
'uw-chinese': {
label: conv({ hans: '请使用标准汉语沟通', hant: '請使用標準漢語溝通' }),
summary: conv({ hans: '提醒:请使用标准汉语沟通', hant: '提醒:請使用標準漢語溝通' })
},
'uw-coi': {
label: conv({ hans: '利益冲突', hant: '利益衝突' }),
summary: conv({ hans: '提醒:利益冲突', hant: '提醒:利益衝突' })
},
'uw-concovid19': {
label: conv({ hans: '违反COVID-19条目共识', hant: '違反COVID-19條目共識' }),
summary: conv({ hans: '提醒:违反COVID-19条目共识', hant: '提醒:違反COVID-19條目共識' })
},
'uw-copyright-friendly': {
label: conv({ hans: '初次加入侵犯著作权的内容', hant: '初次加入侵犯版權的內容' }),
summary: conv({ hans: '提醒:初次加入侵犯著作权的内容', hant: '提醒:初次加入侵犯版權的內容' })
},
'uw-copyviorewrite': {
label: conv({ hans: '在侵权页面直接重写条目', hant: '在侵權頁面直接重寫條目' }),
summary: conv({ hans: '提醒:在侵权页面直接重写条目', hant: '提醒:在侵權頁面直接重寫條目' })
},
'uw-crystal': {
label: conv({ hans: '加入臆测或未确认的消息', hant: '加入臆測或未確認的訊息' }),
summary: conv({ hans: '提醒:加入臆测或未确认的消息', hant: '提醒:加入臆測或未確認的訊息' })
},
'uw-csd': {
label: conv({ hans: '快速删除理由不当', hant: '快速刪除理由不當' }),
summary: conv({ hans: '提醒:快速删除理由不当', hant: '提醒:快速刪除理由不當' })
},
'uw-dab': {
label: conv({ hans: '消歧义页格式错误', hant: '消歧義頁格式錯誤' }),
summary: conv({ hans: '提醒:消歧义页格式错误', hant: '提醒:消歧義頁格式錯誤' })
},
'uw-draft': {
label: conv({ hans: '最近创建的页面被移动到草稿', hant: '最近建立的頁面被移動到草稿' }),
summary: conv({ hans: '提醒:最近创建的页面被移动到草稿', hant: '提醒:最近建立的頁面被移動到草稿' })
},
'uw-editsummary': {
label: conv({ hans: '没有使用编辑摘要', hant: '沒有使用編輯摘要' }),
summary: conv({ hans: '提醒:没有使用编辑摘要', hant: '提醒:沒有使用編輯摘要' })
},
'uw-hangon': {
label: conv({ hans: '没有在讨论页说明暂缓快速删除理由', hant: '沒有在討論頁說明暫緩快速刪除理由' }),
summary: conv({ hans: '提醒:没有在讨论页说明暂缓快速删除理由', hant: '提醒:沒有在討論頁說明暫緩快速刪除理由' })
},
'uw-lang': {
label: conv({ hans: '不必要地将文字换成简体或繁体中文', hant: '不必要地將文字換成簡體或繁體中文' }),
summary: conv({ hans: '提醒:不必要地将文字换成简体或繁体中文', hant: '提醒:不必要地將文字換成簡體或繁體中文' })
},
'uw-langmove': {
label: conv({ hans: '不必要地将标题换成简体或繁体中文', hant: '不必要地將標題換成簡體或繁體中文' }),
summary: conv({ hans: '提醒:不必要地将标题换成简体或繁体中文', hant: '提醒:不必要地將標題換成簡體或繁體中文' })
},
'uw-linking': {
label: conv({ hans: '过度加入红字链接或重复蓝字链接', hant: '過度加入紅字連結或重複藍字連結' }),
summary: conv({ hans: '提醒:过度加入红字链接或重复蓝字链接', hant: '提醒:過度加入紅字連結或重複藍字連結' })
},
'uw-minor': {
label: conv({ hans: '不适当地使用小修改选项', hant: '不適當地使用小修改選項' }),
summary: conv({ hans: '提醒:不适当地使用小修改选项', hant: '提醒:不適當地使用小修改選項' })
},
'uw-notaiv': {
label: conv({ hans: '向“当前的破坏”中报告的是用户纷争而不是破坏', hant: '向「當前的破壞」中報告的是用戶紛爭而不是破壞' }),
summary: conv({ hans: '提醒:向“当前的破坏”中报告的是用户纷争而不是破坏', hant: '提醒:向「當前的破壞」中報告的是用戶紛爭而不是破壞' })
},
'uw-notvote': {
label: conv({ hans: '我们以共识处事,而不仅仅是投票', hant: '我們以共識處事,而不僅僅是投票' }),
summary: conv({ hans: '提醒:我们以共识处事,而不仅仅是投票', hant: '提醒:我們以共識處事,而不僅僅是投票' })
},
'uw-preview': {
label: conv({ hans: '请使用预览按钮来避免不必要的错误', hant: '請使用預覽按鈕來避免不必要的錯誤' }),
summary: conv({ hans: '提醒:请使用预览按钮来避免不必要的错误', hant: '提醒:請使用預覽按鈕來避免不必要的錯誤' })
},
'uw-sandbox': {
label: conv({ hans: '移除沙盒的置顶模板{{sandbox}}', hant: '移除沙盒的置頂模板{{sandbox}}' }),
summary: conv({ hans: '提醒:移除沙盒的置顶模板{{sandbox}}', hant: '提醒:移除沙盒的置頂模板{{sandbox}}' })
},
'uw-selfrevert': {
label: conv({ hans: '感谢您自行回退自己的测试,以后不要再这样做了', hant: '感謝您自行回退自己的測試,以後不要再這樣做了' }),
summary: conv({ hans: '提醒:回退个人的测试', hant: '提醒:回退個人的測試' })
},
'uw-subst': {
label: conv({ hans: '谨记要替代模板(subst)', hant: '謹記要替代模板(subst)' }),
summary: conv({ hans: '提醒:谨记要替代模板', hant: '提醒:謹記要替代模板' })
},
'uw-talkinarticle': {
label: conv({ hans: '在条目页中留下意见', hant: '在條目頁中留下意見' }),
summary: conv({ hans: '提醒:在条目页中留下意见', hant: '提醒:在條目頁中留下意見' })
},
'uw-tilde': {
label: conv({ hans: '没有在讨论页上签名', hant: '沒有在討論頁上簽名' }),
summary: conv({ hans: '提醒:没有在讨论页上签名', hant: '提醒:沒有在討論頁上簽名' })
},
'uw-translated': {
label: conv({ hans: '翻译条目未标注原作者', hant: '翻譯條目未標註原作者' }),
summary: conv({ hans: '提醒:翻译条目未标注原作者', hant: '提醒:翻譯條目未標註原作者' })
},
'uw-uaa': {
label: conv({ hans: '向不当用户名布告板报告的用户名并不违反方针', hant: '向不當使用者名稱布告板報告的使用者名稱並不違反方針' }),
summary: conv({ hans: '提醒:向不当用户名布告板报告的用户名并不违反方针', hant: '提醒:向不當使用者名稱布告板報告的使用者名稱並不違反方針' })
},
'uw-warn': {
label: conv({ hans: '警告破坏用户', hant: '警告破壞用戶' }),
summary: conv({ hans: '提醒:警告破坏用户', hant: '提醒:警告破壞用戶' })
},
'uw-mosiw': {
label: conv({ hans: '不要使用跨语言链接', hant: '不要使用跨語言連結' }),
summary: conv({ hans: '提醒:不要使用跨语言链接', hant: '提醒:不要使用跨語言連結' })
},
'uw-badtwinkle': {
label: conv({ hans: '不恰当地使用Twinkle警告别人', hant: '不恰當地使用Twinkle警告別人' }),
summary: conv({ hans: '提醒:不恰当地使用Twinkle警告别人', hant: '提醒:不恰當地使用Twinkle警告別人' })
}
},
singlewarn: {
'uw-3rr': {
label: conv({ hans: '用户潜在违反回退不过三原则的可能性', hant: '用戶潛在違反回退不過三原則的可能性' }),
summary: conv({ hans: '警告:用户潜在违反回退不过三原则的可能性', hant: '警告:用戶潛在違反回退不過三原則的可能性' })
},
'uw-attack': {
label: conv({ hans: '创建人身攻击页面', hant: '建立人身攻擊頁面' }),
summary: conv({ hans: '警告:创建人身攻击页面', hant: '警告:建立人身攻擊頁面' }),
suppressArticleInSummary: true
},
'uw-bv': {
label: conv({ hans: '公然地破坏', hant: '公然地破壞' }),
summary: conv({ hans: '警告:公然地破坏', hant: '警告:公然地破壞' })
},
'uw-canvass': {
label: conv({ hans: '不恰当地拉票', hant: '不恰當地拉票' }),
summary: conv({ hans: '警告:不恰当地拉票', hant: '警告:不恰當地拉票' })
},
'uw-copyright': {
label: conv({ hans: '侵犯著作权', hant: '侵犯版權' }),
summary: conv({ hans: '警告:侵犯著作权', hant: '警告:侵犯版權' })
},
'uw-copyright-link': {
label: conv({ hans: '链接到有著作权的材料', hant: '連結到有版權的材料' }),
summary: conv({ hans: '警告:链接到有著作权的材料', hant: '警告:連結到有版權的材料' })
},
'uw-fakesource': {
label: conv({ hans: '虚构数据源或引文', hant: '虛構資料來源或引文' }),
summary: conv({ hans: '警告:虚构数据源或引文', hant: '警告:虛構資料來源或引文' })
},
'uw-hoax': {
label: conv({ hans: '创建恶作剧', hant: '建立惡作劇' }),
summary: conv({ hans: '警告:创建恶作剧', hant: '警告:建立惡作劇' })
},
'uw-incompletecite': {
label: conv({ hans: '列出的数据源欠缺若干详情而不易查找', hant: '列出的資料來源欠缺若干詳情而不易查找' }),
summary: conv({ hans: '警告:列出的数据源欠缺若干详情而不易查找', hant: '警告:列出的資料來源欠缺若干詳情而不易查找' })
},
'uw-legal': {
label: conv({ hans: '诉诸法律威胁', hant: '訴諸法律威脅' }),
summary: conv({ hans: '警告:诉诸法律威胁', hant: '警告:訴諸法律威脅' })
},
'uw-longterm': {
label: conv({ hans: '长期的破坏', hant: '長期的破壞' }),
summary: conv({ hans: '警告:长期的破坏', hant: '警告:長期的破壞' })
},
'uw-multipleIPs': {
label: conv({ hans: '使用多个IP地址进行破坏', hant: '使用多個IP地址進行破壞' }),
summary: conv({ hans: '警告:使用多个IP地址进行破坏', hant: '警告:使用多個IP地址進行破壞' })
},
'uw-npov-tvd': {
label: conv({ hans: '在剧集条目中加入奸角等非中立描述', hant: '在劇集條目中加入奸角等非中立描述' }),
summary: conv({ hans: '警告:在剧集条目中加入奸角等非中立描述', hant: '警告:在劇集條目中加入奸角等非中立描述' })
},
'uw-owntalk': {
label: conv({ hans: '匿名用户移除自己讨论页上7日内的讨论', hant: '匿名使用者移除自己討論頁上7日內的討論' }),
summary: conv({ hans: '警告:匿名用户移除自己讨论页上7日内的讨论', hant: '警告:匿名使用者移除自己討論頁上7日內的討論' })
},
'uw-pinfo': {
label: conv({ hans: '张贴他人隐私', hant: '張貼他人隱私' }),
summary: conv({ hans: '警告:张贴他人隐私', hant: '警告:張貼他人隱私' })
},
'uw-upv': {
label: conv({ hans: '破坏他人用户页', hant: '破壞他人用戶頁' }),
summary: conv({ hans: '警告:破坏他人用户页', hant: '警告:破壞他人用戶頁' })
},
'uw-selfinventedname': {
label: conv({ hans: '不适当地自创新名词、新译名', hant: '不適當地自創新名詞、新譯名' }),
summary: conv({ hans: '警告:不适当地自创新名词、新译名', hant: '警告:不適當地自創新名詞、新譯名' })
},
'uw-substub': {
label: conv({ hans: '创建小小作品', hant: '建立小小作品' }),
summary: conv({ hans: '警告:创建小小作品', hant: '警告:建立小小作品' })
},
'uw-username': {
label: conv({ hans: '使用不恰当的用户名', hant: '使用不恰當的用戶名' }),
summary: conv({ hans: '警告:使用不恰当的用户名', hant: '警告:使用不恰當的用戶名' }),
suppressArticleInSummary: true
},
'uw-wrongsummary': {
label: conv({ hans: '在编辑摘要制造不适当的内容', hant: '在編輯摘要製造不適當的內容' }),
summary: conv({ hans: '警告:在编辑摘要制造不适当的内容', hant: '警告:在編輯摘要製造不適當的內容' })
}
}
};
// Used repeatedly below across menu rebuilds
Twinkle.warn.prev_article = null;
Twinkle.warn.prev_reason = null;
Twinkle.warn.talkpageObj = null;
Twinkle.warn.callback.change_category = function twinklewarnCallbackChangeCategory(e) {
var value = e.target.value;
var sub_group = e.target.root.sub_group;
sub_group.main_group = value;
var old_subvalue = sub_group.value;
var old_subvalue_re;
if (old_subvalue) {
if (value === 'kitchensink') { // Exact match possible in kitchensink menu
old_subvalue_re = new RegExp(mw.util.escapeRegExp(old_subvalue));
} else {
old_subvalue = old_subvalue.replace(/\d*(im)?$/, '');
old_subvalue_re = new RegExp(mw.util.escapeRegExp(old_subvalue) + '(\\d*(?:im)?)$');
}
}
while (sub_group.hasChildNodes()) {
sub_group.removeChild(sub_group.firstChild);
}
var selected = false;
// worker function to create the combo box entries
var createEntries = function(contents, container, wrapInOptgroup, val) {
val = typeof val !== 'undefined' ? val : value; // IE doesn't support default parameters
// level2->2, singlewarn->''; also used to distinguish the
// scaled levels from singlenotice, singlewarn, and custom
var level = val.replace(/^\D+/g, '');
// due to an apparent iOS bug, we have to add an option-group to prevent truncation of text
// (search WT:TW archives for "Problem selecting warnings on an iPhone")
if (wrapInOptgroup && $.client.profile().platform === 'iphone') {
var wrapperOptgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: '可用模板'
});
wrapperOptgroup = wrapperOptgroup.render();
container.appendChild(wrapperOptgroup);
container = wrapperOptgroup;
}
$.each(contents, function(itemKey, itemProperties) {
// Skip if the current template doesn't have a version for the current level
if (!!level && !itemProperties[val]) {
return;
}
var key = typeof itemKey === 'string' ? itemKey : itemProperties.value;
var template = key + level;
var elem = new Morebits.quickForm.element({
type: 'option',
label: '{{' + template + '}}: ' + (level ? itemProperties[val].label : itemProperties.label),
value: template
});
// Select item best corresponding to previous selection
if (!selected && old_subvalue && old_subvalue_re.test(template)) {
elem.data.selected = selected = true;
}
var elemRendered = container.appendChild(elem.render());
$(elemRendered).data('messageData', itemProperties);
});
};
switch (value) {
case 'singlenotice':
case 'singlewarn':
createEntries(Twinkle.warn.messages[value], sub_group, true);
break;
case 'singlecombined':
var unSortedSinglets = $.extend({}, Twinkle.warn.messages.singlenotice, Twinkle.warn.messages.singlewarn);
var sortedSingletMessages = {};
Object.keys(unSortedSinglets).sort().forEach(function(key) {
sortedSingletMessages[key] = unSortedSinglets[key];
});
createEntries(sortedSingletMessages, sub_group, true);
break;
case 'custom':
createEntries(Twinkle.getPref('customWarningList'), sub_group, true);
break;
case 'kitchensink':
['level1', 'level2', 'level3', 'level4', 'level4im'].forEach(function(lvl) {
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
createEntries(levelGroup.list, sub_group, true, lvl);
});
});
createEntries(Twinkle.warn.messages.singlenotice, sub_group, true);
createEntries(Twinkle.warn.messages.singlewarn, sub_group, true);
createEntries(Twinkle.getPref('customWarningList'), sub_group, true);
break;
case 'level1':
case 'level2':
case 'level3':
case 'level4':
case 'level4im':
// Creates subgroup regardless of whether there is anything to place in it;
// leaves "Removal of deletion tags" empty for 4im
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: levelGroup.category
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(levelGroup.list, optgroup, false);
});
break;
case 'autolevel':
// Check user page to determine appropriate level
var autolevelProc = function() {
var wikitext = Twinkle.warn.talkpageObj.getPageText();
// history not needed for autolevel
var latest = Twinkle.warn.callbacks.dateProcessing(wikitext)[0];
// Pseudo-params with only what's needed to parse the level i.e. no messageData
var params = {
sub_group: old_subvalue,
article: e.target.root.article.value
};
var lvl = 'level' + Twinkle.warn.callbacks.autolevelParseWikitext(wikitext, params, latest)[1];
// Identical to level1, etc. above but explicitly provides the level
$.each(Twinkle.warn.messages.levels, function(_, levelGroup) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: levelGroup.category
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(levelGroup.list, optgroup, false, lvl);
});
// Trigger subcategory change, add select menu, etc.
Twinkle.warn.callback.postCategoryCleanup(e);
};
if (Twinkle.warn.talkpageObj) {
autolevelProc();
} else {
if (Twinkle.warn.isFlow) {
var $noTalkPageNode = $('<strong/>', {
text: conv({ hans: '结构式讨论(Flow)不支持自动选择警告层级,请手动选择层级。', hant: '結構式討論(Flow)不支援自動選擇警告層級,請手動選擇層級。' }),
id: 'twinkle-warn-autolevel-message',
css: {color: 'red' }
});
$noTalkPageNode.insertBefore($('#twinkle-warn-warning-messages'));
// If a preview was opened while in a different mode, close it
// Should nullify the need to catch the error in preview callback
e.target.root.previewer.closePreview();
} else {
var usertalk_page = new Morebits.wiki.page('User_talk:' + Morebits.wiki.flow.relevantUserName(), conv({ hans: '加载上次警告', hant: '載入上次警告' }));
usertalk_page.setFollowRedirect(true, false);
usertalk_page.load(function(pageobj) {
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj
autolevelProc();
}, function() {
// Catch and warn if the talkpage can't load,
// most likely because it's a cross-namespace redirect
// Supersedes the typical $autolevelMessage added in autolevelParseWikitext
var $noTalkPageNode = $('<strong/>', {
text: conv({ hans: '无法加载用户讨论页,这可能是因为它是跨命名空间重定向,自动选择警告级别将不会运作。', hant: '無法載入使用者討論頁,這可能是因為它是跨命名空間重新導向,自動選擇警告級別將不會運作。' }),
id: 'twinkle-warn-autolevel-message',
css: {color: 'red' }
});
$noTalkPageNode.insertBefore($('#twinkle-warn-warning-messages'));
// If a preview was opened while in a different mode, close it
// Should nullify the need to catch the error in preview callback
e.target.root.previewer.closePreview();
});
}
}
break;
default:
alert(conv({ hans: 'twinklewarn中未知的警告组', hant: 'twinklewarn中未知的警告組' }));
break;
}
// Trigger subcategory change, add select menu, etc.
// Here because of the async load for autolevel
if (value !== 'autolevel') {
// reset any autolevel-specific messages while we're here
$('#twinkle-warn-autolevel-message').remove();
Twinkle.warn.callback.postCategoryCleanup(e);
}
};
Twinkle.warn.callback.postCategoryCleanup = function twinklewarnCallbackPostCategoryCleanup(e) {
// clear overridden label on article textbox
Morebits.quickForm.setElementTooltipVisibility(e.target.root.article, true);
Morebits.quickForm.resetElementLabel(e.target.root.article);
// Trigger custom label/change on main category change
Twinkle.warn.callback.change_subcategory(e);
// Use select2 to make the select menu searchable
if (!Twinkle.getPref('oldSelect')) {
$('select[name=sub_group]')
.select2({
width: '100%',
matcher: Morebits.select2.matchers.optgroupFull,
templateResult: Morebits.select2.highlightSearchMatches,
language: {
searching: Morebits.select2.queryInterceptor
}
})
.change(Twinkle.warn.callback.change_subcategory);
$('.select2-selection').keydown(Morebits.select2.autoStart).focus();
mw.util.addCSS(
// Increase height
'.select2-container .select2-dropdown .select2-results > .select2-results__options { max-height: 350px; }' +
// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
'.select2-results .select2-results__group { padding-top: 1px; padding-bottom: 1px; } ' +
// Adjust font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }'
);
}
};
Twinkle.warn.callback.change_subcategory = function twinklewarnCallbackChangeSubcategory(e) {
var main_group = e.target.form.main_group.value;
var value = e.target.form.sub_group.value;
// Tags that don't take a linked article, but something else (often a username).
// The value of each tag is the label next to the input field
var notLinkedArticle = {
'uw-bite': conv({ hans: '被“咬到”的用户(不含User:) ', hant: '被「咬到」的使用者(不含User:) ' }),
'uw-username': conv({ hans: '用户名违反方针,因为… ', hant: '使用者名稱違反方針,因為… ' }),
'uw-aiv': conv({ hans: '可选输入被警告的用户名(不含User:) ', hant: '可選輸入被警告的使用者名稱(不含User:) ' })
};
if (['singlenotice', 'singlewarn', 'singlecombined', 'kitchensink'].indexOf(main_group) !== -1) {
if (notLinkedArticle[value]) {
if (Twinkle.warn.prev_article === null) {
Twinkle.warn.prev_article = e.target.form.article.value;
}
e.target.form.article.notArticle = true;
e.target.form.article.value = '';
// change form labels according to the warning selected
Morebits.quickForm.setElementTooltipVisibility(e.target.form.article, false);
Morebits.quickForm.overrideElementLabel(e.target.form.article, notLinkedArticle[value]);
} else if (e.target.form.article.notArticle) {
if (Twinkle.warn.prev_article !== null) {
e.target.form.article.value = Twinkle.warn.prev_article;
Twinkle.warn.prev_article = null;
}
e.target.form.article.notArticle = false;
Morebits.quickForm.setElementTooltipVisibility(e.target.form.article, true);
Morebits.quickForm.resetElementLabel(e.target.form.article);
}
}
// add big red notice, warning users about how to use {{uw-[coi-]username}} appropriately
$('#tw-warn-red-notice').remove();
var $redWarning;
if (value === 'uw-username') {
$redWarning = $(conv({
hans: "<div style='color: red;' id='tw-warn-red-notice'>{{uw-username}}<b>不应</b>被用于<b>明显</b>违反用户名方针的用户。" +
'明显的违反方针应被报告给UAA。' +
'{{uw-username}}应只被用在边界情况下需要与用户讨论时。</div>',
hant: "<div style='color: red;' id='tw-warn-red-notice'>{{uw-username}}<b>不應</b>被用於<b>明顯</b>違反用戶名方針的用戶。" +
'明顯的違反方針應被報告給UAA。' +
'{{uw-username}}應只被用在邊界情況下需要與用戶討論時。</div>'
}));
$redWarning.insertAfter(Morebits.quickForm.getElementLabelObject(e.target.form.reasonGroup));
}
};
Twinkle.warn.callbacks = {
getWarningWikitext: function(templateName, article, reason, isCustom, noSign) {
var text = '{{subst:' + templateName;
// add linked article for user warnings
if (article) {
text += '|1=' + article;
}
if (reason) {
// add extra message
if (templateName === 'uw-csd') {
text += '|3=' + reason;
} else {
text += '|2=' + reason;
}
}
text += '|subst=subst:}}';
if (!noSign) {
text += ' ~~~~';
}
return text;
},
showPreview: function(form, templatename) {
var input = Morebits.quickForm.getInputData(form);
// Provided on autolevel, not otherwise
templatename = templatename || input.sub_group;
var linkedarticle = input.article;
var templatetext;
templatetext = Twinkle.warn.callbacks.getWarningWikitext(templatename, linkedarticle,
input.reason, input.main_group === 'custom');
form.previewer.beginRender(templatetext, 'User_talk:' + Morebits.wiki.flow.relevantUserName() + (Twinkle.warn.isFlow ? '/Wikitext' : '')); // Force wikitext/correct username
},
// Just a pass-through unless the autolevel option was selected
preview: function(form) {
if (form.main_group.value === 'autolevel') {
// Always get a new, updated talkpage for autolevel processing
var usertalk_page = new Morebits.wiki.page('User_talk:' + Morebits.wiki.flow.relevantUserName(), conv({ hans: '加载上次警告', hant: '載入上次警告' }));
usertalk_page.setFollowRedirect(true, false);
// Will fail silently if the talk page is a cross-ns redirect,
// removal of the preview box handled when loading the menu
usertalk_page.load(function(pageobj) {
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj
var wikitext = pageobj.getPageText();
// history not needed for autolevel
var latest = Twinkle.warn.callbacks.dateProcessing(wikitext)[0];
var params = {
sub_group: form.sub_group.value,
article: form.article.value,
messageData: $(form.sub_group).find('option[value="' + $(form.sub_group).val() + '"]').data('messageData')
};
var template = Twinkle.warn.callbacks.autolevelParseWikitext(wikitext, params, latest)[0];
Twinkle.warn.callbacks.showPreview(form, template);
// If the templates have diverged, fake a change event
// to reload the menu with the updated pageobj
if (form.sub_group.value !== template) {
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
form.main_group.dispatchEvent(evt);
}
});
} else {
Twinkle.warn.callbacks.showPreview(form);
}
},
/**
* Used in the main and autolevel loops to determine when to warn
* about excessively recent, stale, or identical warnings.
* @param {string} wikitext The text of a user's talk page, from getPageText()
* @returns {Object[]} - Array of objects: latest contains most recent
* warning and date; history lists all prior warnings
*/
dateProcessing: function(wikitext) {
var history_re = /<!--\s?Template:([uU]w-.*?)\s?-->.*?(\d{4})年(\d{1,2})月(\d{1,2})日 \([日一二三四五六]\) (\d{1,2}):(\d{1,2}) \(UTC\)/g;
var history = {};
var latest = { date: new Morebits.date(0), type: '' };
var current;
while ((current = history_re.exec(wikitext)) !== null) {
var template = current[1];
var current_date = new Morebits.date(current[2] + '-' + current[3] + '-' + current[4] + ' ' + current[5] + ':' + current[6] + ' UTC');
if (!(template in history) || history[template].isBefore(current_date)) {
history[template] = current_date;
}
if (!latest.date.isAfter(current_date)) {
latest.date = current_date;
latest.type = template;
}
}
return [latest, history];
},
/**
* Main loop for deciding what the level should increment to. Most of
* this is really just error catching and updating the subsequent data.
* May produce up to two notices in a twinkle-warn-autolevel-messages div
*
* @param {string} wikitext The text of a user's talk page, from getPageText() (required)
* @param {Object} params Params object: sub_group is the template (required);
* article is the user-provided article (form.article) used to link ARV on recent level4 warnings;
* messageData is only necessary if getting the full template, as it's
* used to ensure a valid template of that level exists
* @param {Object} latest First element of the array returned from
* dateProcessing. Provided here rather than processed within to avoid
* repeated call to dateProcessing
* @param {(Date|Morebits.date)} date Date from which staleness is determined
* @param {Morebits.status} statelem Status element, only used for handling error in final execution
*
* @returns {Array} - Array that contains the full template and just the warning level
*/
autolevelParseWikitext: function(wikitext, params, latest, date, statelem) {
var level; // undefined rather than '' means the isNaN below will return true
if (/\d(?:im)?$/.test(latest.type)) { // level1-4im
level = parseInt(latest.type.replace(/.*(\d)(?:im)?$/, '$1'), 10);
} else if (latest.type) { // Non-numbered warning
// Try to leverage existing categorization of
// warnings, all but one are universally lowercased
var loweredType = /uw-multipleIPs/i.test(latest.type) ? 'uw-multipleIPs' : latest.type.toLowerCase();
// It would be nice to account for blocks, but in most
// cases the hidden message is terminal, not the sig
if (Twinkle.warn.messages.singlewarn[loweredType]) {
level = 3;
} else {
level = 1; // singlenotice or not found
}
}
var $autolevelMessage = $('<div/>', {id: 'twinkle-warn-autolevel-message'});
if (isNaN(level)) { // No prior warnings found, this is the first
level = 1;
} else if (level > 4 || level < 1) { // Shouldn't happen
var message = conv({ hans: '无法解析上次的警告层级,请手动选择一个警告层级。', hant: '無法解析上次的警告層級,請手動選擇一個警告層級。' });
if (statelem) {
statelem.error(message);
} else {
alert(message);
}
return;
} else {
date = date || new Date();
var autoTimeout = new Morebits.date(latest.date.getTime()).add(parseInt(Twinkle.getPref('autolevelStaleDays'), 10), 'day');
if (autoTimeout.isAfter(date)) {
if (level === 4) {
level = 4;
// Basically indicates whether we're in the final Main evaluation or not,
// and thus whether we can continue or need to display the warning and link
if (!statelem) {
var $link = $('<a/>', {
href: '#',
text: conv({ hans: '单击此处打开告状工具', hant: '點擊此處打開告狀工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.warn.dialog.close();
Twinkle.arv.callback(Morebits.wiki.flow.relevantUserName());
$('input[name=page]').val(params.article); // Target page
$('input[value=final]').prop('checked', true); // Vandalism after final
}
});
var statusNode = $('<div/>', {
text: Morebits.wiki.flow.relevantUserName() + conv({ hans: '最后收到了一个层级4警告(', hant: '最後收到了一個層級4警告(' }) + latest.type + conv({ hans: '),所以将其报告给管理人员会比较好;', hant: '),所以將其報告給管理人員會比較好;' }),
css: {color: 'red' }
});
statusNode.append($link[0]);
$autolevelMessage.append(statusNode);
}
} else { // Automatically increase severity
level += 1;
}
} else { // Reset warning level if most-recent warning is too old
level = 1;
}
}
$autolevelMessage.prepend($('<div>' + conv({ hans: '将发送', hant: '將發送' }) + '<span style="font-weight: bold;">' + conv({ hans: '层级', hant: '層級' }) + level + '</span>' + '警告模板' + '。</div>'));
// Place after the stale and other-user-reverted (text-only) messages
$('#twinkle-warn-autolevel-message').remove(); // clean slate
$autolevelMessage.insertAfter($('#twinkle-warn-warning-messages'));
var template = params.sub_group.replace(/(.*)\d$/, '$1');
// Validate warning level, falling back to the uw-generic series.
// Only a few items are missing a level, and in all but a handful
// of cases, the uw-generic series is explicitly used elsewhere per WP:UTM.
if (params.messageData && !params.messageData['level' + level]) {
template = 'uw-generic';
}
template += level;
return [template, level];
},
main: function(pageobj) {
var text = pageobj.getPageText();
var statelem = pageobj.getStatusElement();
var params = pageobj.getCallbackParameters();
var messageData = params.messageData;
// JS somehow didn't get destructured assignment until ES6 so of course IE doesn't support it
var warningHistory = Twinkle.warn.callbacks.dateProcessing(text);
var latest = warningHistory[0];
var history = warningHistory[1];
var now = new Morebits.date(pageobj.getLoadTime());
Twinkle.warn.talkpageObj = pageobj; // Update talkpageObj, just in case
if (params.main_group === 'autolevel') {
// [template, level]
var templateAndLevel = Twinkle.warn.callbacks.autolevelParseWikitext(text, params, latest, now, statelem);
// Only if there's a change from the prior display/load
if (params.sub_group !== templateAndLevel[0] && !confirm(conv({ hans: '将发送给用户{{', hant: '將發送給使用者{{' }) + templateAndLevel[0] + conv({ hans: '}}模板,好吗?', hant: '}}模板,好嗎?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
// Update params now that we've selected a warning
params.sub_group = templateAndLevel[0];
messageData = params.messageData['level' + templateAndLevel[1]];
} else if (params.sub_group in history) {
if (new Morebits.date(history[params.sub_group]).add(1, 'day').isAfter(now)) {
if (!confirm(conv({ hans: '近24小时内一个同样的 ', hant: '近24小時內一個同樣的 ' }) + params.sub_group + conv({ hans: ' 模板已被发出。\n是否继续?', hant: ' 模板已被發出。\n是否繼續?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
}
}
latest.date.add(1, 'minute'); // after long debate, one minute is max
if (latest.date.isAfter(now)) {
if (!confirm(conv({ hans: '近1分钟内 ', hant: '近1分鐘內 ' }) + latest.type + conv({ hans: ' 模板已被发出。\n是否继续?', hant: ' 模板已被發出。\n是否繼續?' }))) {
statelem.error(conv({ hans: '用户取消', hant: '使用者取消' }));
return;
}
}
// build the edit summary
// Function to handle generation of summary prefix for custom templates
var customProcess = function(template) {
template = template.split('|')[0];
var prefix;
switch (template.substr(-1)) {
case '1':
prefix = '提醒';
break;
case '2':
prefix = '注意';
break;
case '3':
prefix = '警告';
break;
case '4':
prefix = conv({ hans: '最后警告', hant: '最後警告' });
break;
case 'm':
if (template.substr(-3) === '4im') {
prefix = '唯一警告';
break;
}
// falls through
default:
prefix = '提醒';
break;
}
return prefix + ':' + Morebits.string.toUpperCaseFirstChar(messageData.label);
};
var summary;
if (params.main_group === 'custom') {
summary = customProcess(params.sub_group);
} else {
// Normalize kitchensink to the 1-4im style
if (params.main_group === 'kitchensink' && !/^D+$/.test(params.sub_group)) {
var sub = params.sub_group.substr(-1);
if (sub === 'm') {
sub = params.sub_group.substr(-3);
}
// Don't overwrite uw-3rr, technically unnecessary
if (/\d/.test(sub)) {
params.main_group = 'level' + sub;
}
}
// singlet || level1-4im, no need to /^\D+$/.test(params.main_group)
summary = messageData.summary || (messageData[params.main_group] && messageData[params.main_group].summary);
// Not in Twinkle.warn.messages, assume custom template
if (!summary) {
summary = customProcess(params.sub_group);
}
if (messageData.suppressArticleInSummary !== true && params.article) {
if (params.sub_group === 'uw-aiv') { // these templates require a username
summary += '(' + conv({ hans: '对于', hant: '對於' }) + '[[User:' + params.article + ']])';
} else if (params.sub_group === 'uw-bite') { // this template requires a username
summary += ',' + conv({ hans: '于', hant: '於' }) + '[[User talk:' + params.article + ']]';
} else {
summary += conv({ hans: ',于[[', hant: ',於[[' }) + params.article + ']]';
}
}
}
pageobj.setEditSummary(summary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchWarnings'));
// Get actual warning text
var warningText = Twinkle.warn.callbacks.getWarningWikitext(params.sub_group, params.article,
params.reason, params.main_group === 'custom');
if (Twinkle.getPref('showSharedIPNotice') && mw.util.isIPAddress(mw.config.get('wgTitle'))) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入共享IP说明', hant: '加入共享IP說明' }));
warningText += '\n{{subst:SharedIPAdvice}}';
}
var sectionExists = false, sectionNumber = 0;
// Only check sections if there are sections or there's a chance we won't create our own
if (!messageData.heading && text.length) {
// Get all sections
var sections = text.match(/^(==*).+\1/gm);
if (sections && sections.length !== 0) {
// Find the index of the section header in question
var dateHeaderRegex = now.monthHeaderRegex();
sectionNumber = 0;
// Find this month's section among L2 sections, preferring the bottom-most
sectionExists = sections.reverse().some(function(sec, idx) {
return /^(==)[^=].+\1/m.test(sec) && dateHeaderRegex.test(sec) && typeof (sectionNumber = sections.length - 1 - idx) === 'number';
});
}
}
if (sectionExists) { // append to existing section
pageobj.setPageSection(sectionNumber + 1);
pageobj.setAppendText('\n\n' + warningText);
pageobj.append();
} else {
if (messageData.heading) { // create new section
pageobj.setNewSectionTitle(messageData.heading);
} else {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '未找到当月的二级标题,将创建新的', hant: '未找到當月的二級標題,將建立新的' }));
pageobj.setNewSectionTitle(now.monthHeader(0));
}
pageobj.setNewSectionText(warningText);
pageobj.newSection();
}
},
main_flow: function (flowobj) {
var params = flowobj.getCallbackParameters();
var messageData = params.messageData;
// build the edit summary
// Function to handle generation of summary prefix for custom templates
var customProcess = function(template) {
template = template.split('|')[0];
var prefix;
switch (template.substr(-1)) {
case '1':
prefix = '提醒';
break;
case '2':
prefix = '注意';
break;
case '3':
prefix = '警告';
break;
case '4':
prefix = conv({ hans: '最后警告', hant: '最後警告' });
break;
case 'm':
if (template.substr(-3) === '4im') {
prefix = '唯一警告';
break;
}
// falls through
default:
prefix = '提醒';
break;
}
return prefix + ':' + Morebits.string.toUpperCaseFirstChar(messageData.label);
};
var topic;
if (messageData.heading) {
topic = messageData.heading;
} else {
// Normalize kitchensink to the 1-4im style
if (params.main_group === 'kitchensink' && !/^D+$/.test(params.sub_group)) {
var sub = params.sub_group.substr(-1);
if (sub === 'm') {
sub = params.sub_group.substr(-3);
}
// Don't overwrite uw-3rr, technically unnecessary
if (/\d/.test(sub)) {
params.main_group = 'level' + sub;
}
}
// singlet || level1-4im, no need to /^\D+$/.test(params.main_group)
topic = messageData.summary || (messageData[params.main_group] && messageData[params.main_group].summary);
// Not in Twinkle.warn.messages, assume custom template
if (!topic) {
topic = customProcess(params.sub_group);
}
}
var content = Twinkle.warn.callbacks.getWarningWikitext(params.sub_group, params.article,
params.reason, params.main_group === 'custom', true);
flowobj.setTopic(topic);
flowobj.setContent(content);
flowobj.newTopic();
}
};
Twinkle.warn.callback.evaluate = function twinklewarnCallbackEvaluate(e) {
var userTalkPage = 'User_talk:' + Morebits.wiki.flow.relevantUserName();
// reason, main_group, sub_group, article
var params = Morebits.quickForm.getInputData(e.target);
// Check that a reason was filled in if uw-username was selected
if (params.sub_group === 'uw-username' && !params.article) {
alert(conv({ hans: '必须给{{uw-username}}提供理由。', hant: '必須給{{uw-username}}提供理由。' }));
return;
}
if (params.article) {
if (/https?:\/\//.test(params.article)) {
alert(conv({ hans: '“页面链接”不能使用网址。', hant: '「頁面連結」不能使用網址。' }));
return;
}
try {
var article = new mw.Title(params.article);
params.article = article.getPrefixedText();
if (article.getFragment()) {
params.article += '#' + article.getFragment();
}
} catch (error) {
alert(conv({ hans: '“页面链接”不合法,仅能输入一个页面名称,勿使用网址、[[ ]],可使用Special:Diff。', hant: '「頁面連結」不合法,僅能輸入一個頁面名稱,勿使用網址、[[ ]],可使用Special:Diff。' }));
return;
}
}
// The autolevel option will already know by now if a user talk page
// is a cross-namespace redirect (via !!Twinkle.warn.talkpageObj), so
// technically we could alert an error here, but the user will have
// already ignored the bold red error above. Moreover, they probably
// *don't* want to actually issue a warning, so the error handling
// after the form is submitted is probably preferable
// Find the selected <option> element so we can fetch the data structure
var $selectedEl = $(e.target.sub_group).find('option[value="' + $(e.target.sub_group).val() + '"]');
params.messageData = $selectedEl.data('messageData');
if (typeof params.messageData === 'undefined') {
alert(conv({ hans: '请选择警告模板。', hant: '請選擇警告模板。' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '警告完成,将在几秒后刷新', hant: '警告完成,將在幾秒後重新整理' });
if (Twinkle.warn.isFlow) {
var flow_page = new Morebits.wiki.flow(userTalkPage, conv({ hans: '用户Flow讨论页留言', hant: '使用者Flow討論頁留言' }));
flow_page.setCallbackParameters(params);
Twinkle.warn.callbacks.main_flow(flow_page);
} else {
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '用户讨论页修改', hant: '使用者討論頁修改' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setFollowRedirect(true, false);
wikipedia_page.load(Twinkle.warn.callbacks.main);
}
};
Twinkle.addInitCallback(Twinkle.warn, 'warn');
})(jQuery);
// </nowiki>
0a47614bec17c45ab5164d79eb15e23d93ec53c7
MediaWiki:Gadget-twinkleblock.js
8
153
309
308
2024-08-03T04:07:18Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
var conv = require('ext.gadget.HanAssist').conv;
var api = new mw.Api(), relevantUserName, blockedUserName;
var menuFormattedNamespaces = $.extend({}, mw.config.get('wgFormattedNamespaces'));
menuFormattedNamespaces[0] = conv({ hans: '(条目)', hant: '(條目)' });
var blockActionText = {
block: conv({ hans: '封禁', hant: '封鎖' }),
reblock: conv({ hans: '重新封禁', hant: '重新封鎖' }),
unblock: conv({ hans: '解除封禁', hant: '解除封鎖' })
};
/*
****************************************
*** twinkleblock.js: Block module
****************************************
* Mode of invocation: Tab ("Block")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
*/
Twinkle.block = function twinkleblock() {
relevantUserName = Morebits.wiki.flow.relevantUserName(true);
// should show on Contributions or Block pages, anywhere there's a relevant user
// Ignore ranges wider than the CIDR limit
// zhwiki: Enable for non-admins
if ((Morebits.userIsSysop || !mw.util.isIPAddress(relevantUserName, true)) && relevantUserName && (!Morebits.ip.isRange(relevantUserName) || Morebits.ip.validCIDR(relevantUserName))) {
Twinkle.addPortletLink(Twinkle.block.callback, conv({ hans: '封禁', hant: '封鎖' }), 'tw-block', conv({ hans: '封禁相关用户', hant: '封鎖相關使用者' }));
}
};
Twinkle.block.callback = function twinkleblockCallback() {
if (relevantUserName === mw.config.get('wgUserName') &&
!confirm(conv({ hans: '您即将对自己执行封禁相关操作!确认要继续吗?', hant: '您即將對自己執行封鎖相關操作!確認要繼續嗎?' }))) {
return;
}
Twinkle.block.currentBlockInfo = undefined;
Twinkle.block.field_block_options = {};
Twinkle.block.field_template_options = {};
var Window = new Morebits.simpleWindow(650, 530);
// need to be verbose about who we're blocking
Window.setTitle(conv({ hans: '封禁或向', hant: '封鎖或向' }) + relevantUserName + conv({ hans: '发出封禁模板', hant: '發出封鎖模板' }));
Window.setScriptName('Twinkle');
Window.addFooterLink('封禁模板', 'Wikipedia:模板消息/用戶討論命名空間#封禁');
Window.addFooterLink(conv({ hans: '封禁方针', hant: '封鎖方針' }), 'WP:BLOCK');
Window.addFooterLink(conv({ hans: '封禁设置', hant: '封鎖設定' }), 'WP:TW/PREF#block');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#block');
var form = new Morebits.quickForm(Twinkle.block.callback.evaluate);
var actionfield = form.append({
type: 'field',
label: conv({ hans: '操作类型', hant: '操作類別' })
});
actionfield.append({
type: 'checkbox',
name: 'actiontype',
event: Twinkle.block.callback.change_action,
list: [
{
label: conv({ hans: '封禁用户', hant: '封鎖使用者' }),
value: 'block',
tooltip: conv({ hans: '用选择的选项全站封禁相关用户,如果未勾选部分封禁则为全站封禁。', hant: '用選擇的選項全站封鎖相關使用者,如果未勾選部分封鎖則為全站封鎖。' }),
hidden: !Morebits.userIsSysop,
checked: Morebits.userIsSysop
},
{
label: conv({ hans: '部分封禁', hant: '部分封鎖' }),
value: 'partial',
tooltip: conv({ hans: '启用部分封禁及部分封禁模板。', hant: '啟用部分封鎖及部分封鎖模板。' }),
hidden: !Morebits.userIsSysop,
checked: Twinkle.getPref('defaultToPartialBlocks') // Overridden if already blocked
},
{
label: conv({ hans: '加入封禁模板到用户讨论页', hant: '加入封鎖模板到使用者討論頁' }),
value: 'template',
tooltip: conv({ hans: '如果执行封禁的管理员忘记发出封禁模板,或你封禁了用户而没有给其发出模板,则你可以用此来发出合适的模板。勾选部分封禁以使用部分封禁模板。', hant: '如果執行封鎖的管理員忘記發出封鎖模板,或你封鎖了使用者而沒有給其發出模板,則你可以用此來發出合適的模板。勾選部分封鎖以使用部分封鎖模板。' }),
// Disallow when viewing the block dialog on an IP range
hidden: !Morebits.userIsSysop,
checked: Morebits.userIsSysop && !Morebits.ip.isRange(relevantUserName),
disabled: Morebits.ip.isRange(relevantUserName)
},
{
label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }),
value: 'tag',
tooltip: conv({ hans: '将用户页替换成相关的标记模板,仅限永久封禁使用。', hant: '將使用者頁面替換成相關的標記模板,僅限永久封鎖使用。' }),
hidden: true,
checked: !Morebits.userIsSysop
},
{
label: conv({ hans: '保护用户页', hant: '保護使用者頁面' }),
value: 'protect',
tooltip: conv({ hans: '全保护用户页,仅限永久封禁使用。', hant: '全保護使用者頁面,僅限永久封鎖使用。' }),
hidden: true
},
{
label: conv({ hans: '解除封禁用户', hant: '解除封鎖使用者' }),
value: 'unblock',
tooltip: conv({ hans: '解除封禁相关用户。', hant: '解除封鎖相關使用者。' }),
hidden: !Morebits.userIsSysop
}
]
});
/*
Add option for IPv6 ranges smaller than /64 to upgrade to the 64
CIDR ([[WP:/64]]). This is one of the few places where we want
wgRelevantUserName since this depends entirely on the original user.
In theory, we shouldn't use Morebits.ip.get64 here since since we want
to exclude functionally-equivalent /64s. That'd be:
// if (mw.util.isIPv6Address(Morebits.wiki.flow.relevantUserName(true), true) &&
// (mw.util.isIPv6Address(Morebits.wiki.flow.relevantUserName(true)) || parseInt(Morebits.wiki.flow.relevantUserName(true).replace(/^(.+?)\/?(\d{1,3})?$/, '$2'), 10) > 64)) {
In practice, though, since functionally-equivalent ranges are
(mis)treated as separate by MediaWiki's logging ([[phab:T146628]]),
using Morebits.ip.get64 provides a modicum of relief in thise case.
*/
var sixtyFour = Morebits.ip.get64(Morebits.wiki.flow.relevantUserName(true));
if (sixtyFour && sixtyFour !== Morebits.wiki.flow.relevantUserName(true)) {
var block64field = form.append({
type: 'field',
label: conv({ hans: '转换为/64段封禁', hant: '轉換為/64段封鎖' }),
name: 'field_64'
});
block64field.append({
type: 'div',
style: 'margin-bottom: 0.5em',
label: [$.parseHTML('<a target="_blank" href="' + mw.util.getUrl('en:WP:/64') + '">' + conv({ hans: '直接封禁/64段', hant: '直接封鎖/64段' }) + '</a>')[0], '(',
$.parseHTML('<a target="_blank" href="' + mw.util.getUrl('Special:Contributions/' + sixtyFour) + '">' + sixtyFour + '</a>)')[0], conv({ hans: ')有益无害。', hant: ')有益無害。' })]
});
block64field.append({
type: 'checkbox',
name: 'block64',
event: Twinkle.block.callback.change_block64,
list: [{
checked: Twinkle.getPref('defaultToBlock64'),
label: conv({ hans: '改成封禁/64', hant: '改成封鎖/64' }),
value: 'block64',
tooltip: Morebits.ip.isRange(Morebits.wiki.flow.relevantUserName(true)) ? conv({ hans: '将不会发送模板通知。', hant: '將不會發送模板通知。' }) : conv({ hans: '任何模板将会发送给原始IP:', hant: '任何模板將會發送給原始IP:' }) + Morebits.wiki.flow.relevantUserName(true)
}]
});
}
form.append({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
form.append({ type: 'field', label: conv({ hans: '模板选项', hant: '模板選項' }), name: 'field_template_options' });
form.append({ type: 'field', label: conv({ hans: '封禁选项', hant: '封鎖選項' }), name: 'field_block_options' });
form.append({ type: 'field', label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }), name: 'field_tag_options' });
form.append({ type: 'field', label: conv({ hans: '解除封禁选项', hant: '解除封鎖選項' }), name: 'field_unblock_options' });
form.append({ type: 'submit', label: '提交' });
var result = form.render();
Window.setContent(result);
Window.display();
result.root = result;
Twinkle.block.fetchUserInfo(function() {
if (Twinkle.block.isRegistered) {
var $form = $(result);
Morebits.quickForm.setElementVisibility($form.find('[name=actiontype][value=tag]').parent(), true);
if (Morebits.userIsSysop) {
Morebits.quickForm.setElementVisibility($form.find('[name=actiontype][value=protect]').parent(), true);
}
}
// Toggle initial partial state depending on prior block type,
// will override the defaultToPartialBlocks pref
if (blockedUserName === relevantUserName) {
$(result).find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
}
// clean up preset data (defaults, etc.), done exactly once, must be before Twinkle.block.callback.change_action is called
Twinkle.block.transformBlockPresets();
// init the controls after user and block info have been fetched
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
if (result.block64 && result.block64.checked) {
// Calls the same change_action event once finished
result.block64.dispatchEvent(evt);
} else {
result.actiontype[0].dispatchEvent(evt);
}
});
};
// Store fetched user data, only relevant if switching IPv6 to a /64
Twinkle.block.fetchedData = {};
// Processes the data from a a query response, separated from
// Twinkle.block.fetchUserInfo to allow reprocessing of already-fetched data
Twinkle.block.processUserInfo = function twinkleblockProcessUserInfo(data, fn) {
var blockinfo = data.query.blocks[0],
userinfo = data.query.users[0];
// If an IP is blocked *and* rangeblocked, the above finds
// whichever block is more recent, not necessarily correct.
// Three seems... unlikely
if (data.query.blocks.length > 1 && blockinfo.user !== relevantUserName) {
blockinfo = data.query.blocks[1];
}
// Cache response, used when toggling /64 blocks
Twinkle.block.fetchedData[userinfo.name] = data;
Twinkle.block.isRegistered = !!userinfo.userid;
if (Twinkle.block.isRegistered) {
Twinkle.block.userIsBot = !!userinfo.groupmemberships && userinfo.groupmemberships.map(function(e) {
return e.group;
}).indexOf('bot') !== -1;
} else {
Twinkle.block.userIsBot = false;
}
if (blockinfo) {
// handle frustrating system of inverted boolean values
blockinfo.disabletalk = blockinfo.allowusertalk === undefined;
blockinfo.hardblock = blockinfo.anononly === undefined;
}
// will undefine if no blocks present
Twinkle.block.currentBlockInfo = blockinfo;
blockedUserName = Twinkle.block.currentBlockInfo && Twinkle.block.currentBlockInfo.user;
// Semi-busted on ranges, see [[phab:T270737]] and [[phab:T146628]].
// Basically, logevents doesn't treat functionally-equivalent ranges
// as equivalent, meaning any functionally-equivalent IP range is
// misinterpreted by the log throughout. Without logevents
// redirecting (like Special:Block does) we would need a function to
// parse ranges, which is a pain. IPUtils has the code, but it'd be a
// lot of cruft for one purpose.
Twinkle.block.hasBlockLog = !!data.query.logevents.length;
Twinkle.block.blockLog = Twinkle.block.hasBlockLog && data.query.logevents;
// Used later to check if block status changed while filling out the form
Twinkle.block.blockLogId = Twinkle.block.hasBlockLog ? data.query.logevents[0].logid : false;
if (typeof fn === 'function') {
return fn();
}
};
Twinkle.block.fetchUserInfo = function twinkleblockFetchUserInfo(fn) {
var query = {
format: 'json',
action: 'query',
list: 'blocks|users|logevents',
letype: 'block',
lelimit: 2, // zhwiki: Add more details
letitle: 'User:' + relevantUserName,
bkprop: 'expiry|reason|flags|restrictions|range|user',
ususers: relevantUserName
};
// bkusers doesn't catch single IPs blocked as part of a range block
if (mw.util.isIPAddress(relevantUserName, true)) {
query.bkip = relevantUserName;
} else {
query.bkusers = relevantUserName;
// groupmemberships only relevant for registered users
query.usprop = 'groupmemberships';
}
api.get(query).then(function(data) {
Twinkle.block.processUserInfo(data, fn);
}, function(msg) {
Morebits.status.init($('div[name="currentblock"] span').last()[0]);
Morebits.status.warn(conv({ hans: '抓取用户信息出错', hant: '抓取使用者資訊出錯' }), msg);
});
};
Twinkle.block.callback.saveFieldset = function twinkleblockCallbacksaveFieldset(fieldset) {
Twinkle.block[$(fieldset).prop('name')] = {};
$(fieldset).serializeArray().forEach(function(el) {
// namespaces and pages for partial blocks are overwritten
// here, but we're handling them elsewhere so that's fine
Twinkle.block[$(fieldset).prop('name')][el.name] = el.value;
});
};
Twinkle.block.callback.change_block64 = function twinkleblockCallbackChangeBlock64(e) {
var $form = $(e.target.form), $block64 = $form.find('[name=block64]');
// Show/hide block64 button
// Single IPv6, or IPv6 range smaller than a /64
var priorName = relevantUserName;
if ($block64.is(':checked')) {
relevantUserName = Morebits.ip.get64(Morebits.wiki.flow.relevantUserName(true));
} else {
relevantUserName = Morebits.wiki.flow.relevantUserName(true);
}
// No templates for ranges, but if the original user is a single IP, offer the option
// (done separately in Twinkle.block.callback.issue_template)
var originalIsRange = Morebits.ip.isRange(Morebits.wiki.flow.relevantUserName(true));
$form.find('[name=actiontype][value=template]').prop('disabled', originalIsRange).prop('checked', !originalIsRange);
// Refetch/reprocess user info then regenerate the main content
var regenerateForm = function() {
// Tweak titlebar text. In theory, we could save the dialog
// at initialization and then use `.setTitle` or
// `dialog('option', 'title')`, but in practice that swallows
// the scriptName and requires `.display`ing, which jumps the
// window. It's just a line of text, so this is fine.
var titleBar = document.querySelector('.ui-dialog-title').firstChild.nextSibling;
titleBar.nodeValue = titleBar.nodeValue.replace(priorName, relevantUserName);
// Correct partial state
$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.getPref('defaultToPartialBlocks'));
if (blockedUserName === relevantUserName) {
$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
}
// Set content appropriately
Twinkle.block.callback.change_action(e);
};
if (Twinkle.block.fetchedData[relevantUserName]) {
Twinkle.block.processUserInfo(Twinkle.block.fetchedData[relevantUserName], regenerateForm);
} else {
Twinkle.block.fetchUserInfo(regenerateForm);
}
};
Twinkle.block.callback.change_action = function twinkleblockCallbackChangeAction(e) {
var field_preset, field_template_options, field_block_options, field_tag_options, field_unblock_options, $form = $(e.target.form);
// Make ifs shorter
var $block = $form.find('[name=actiontype][value=block]');
var blockBox = $block.is(':checked');
var $template = $form.find('[name=actiontype][value=template]');
var templateBox = $template.is(':checked');
var $tag = $form.find('[name=actiontype][value=tag]');
var tagBox = $tag.is(':checked');
var $protect = $form.find('[name=actiontype][value=protect]');
var $partial = $form.find('[name=actiontype][value=partial]');
var partialBox = $partial.is(':checked');
var $unblock = $form.find('[name=actiontype][value=unblock]');
var unblockBox = $unblock.is(':checked');
var blockGroup = partialBox ? Twinkle.block.blockGroupsPartial : Twinkle.block.blockGroups;
if (e.target.value === 'unblock') {
if (!Twinkle.block.currentBlockInfo) {
$unblock.prop('checked', false);
return alert(conv({ hans: '用户没有被封禁', hant: '使用者沒有被封鎖' }));
}
$block.prop('checked', false);
blockBox = false;
$template.prop('checked', false);
templateBox = false;
$tag.prop('checked', false);
$protect.prop('checked', false);
$partial.prop('checked', false);
} else {
$unblock.prop('checked', false);
}
$partial.prop('disabled', !blockBox && !templateBox);
// Add current block parameters as default preset
var prior = { label: conv({ hans: '当前封禁', hant: '目前封鎖' }) };
if (blockedUserName === relevantUserName) {
Twinkle.block.blockPresetsInfo.prior = Twinkle.block.currentBlockInfo;
// value not a valid template selection, chosen below by setting templateName
prior.list = [{ label: conv({ hans: '当前封禁设置', hant: '目前封鎖設定' }), value: 'prior', selected: true }];
// Arrays of objects are annoying to check
if (!blockGroup.some(function(bg) {
return bg.label === prior.label;
})) {
blockGroup.push(prior);
}
// Always ensure proper template exists/is selected when switching modes
if (partialBox) {
Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-pblockindef' : 'uw-pblock';
} else {
if (!Twinkle.block.isRegistered) {
Twinkle.block.blockPresetsInfo.prior.templateName = 'uw-ablock';
} else {
Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-blockindef' : 'uw-block';
}
}
} else {
// But first remove any prior prior
blockGroup = blockGroup.filter(function(bg) {
return bg.label !== prior.label;
});
}
Twinkle.block.callback.saveFieldset($('[name=field_block_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_template_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_tag_options]'));
Twinkle.block.callback.saveFieldset($('[name=field_unblock_options]'));
if (blockBox) {
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'preset',
label: conv({ hans: '选择默认:', hant: '選擇預設:' }),
event: Twinkle.block.callback.change_preset,
list: Twinkle.block.callback.filtered_block_groups(blockGroup)
});
field_block_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '封禁选项', hant: '封鎖選項' }), name: 'field_block_options' });
field_block_options.append({ type: 'div', name: 'currentblock', label: ' ' });
field_block_options.append({ type: 'div', name: 'hasblocklog', label: ' ' });
field_block_options.append({
type: 'select',
name: 'expiry_preset',
label: conv({ hans: '过期时间:', hant: '過期時間:' }),
event: Twinkle.block.callback.change_expiry,
list: [
{ label: conv({ hans: '自定义', hant: '自訂' }), value: 'custom', selected: true },
{ label: conv({ hans: '无限期', hant: '無限期' }), value: 'infinity' },
{ label: conv({ hans: '3小时', hant: '3小時' }), value: '3 hours' },
{ label: conv({ hans: '12小时', hant: '12小時' }), value: '12 hours' },
{ label: '1天', value: '1 day' },
{ label: conv({ hans: '31小时', hant: '31小時' }), value: '31 hours' },
{ label: '2天', value: '2 days' },
{ label: '3天', value: '3 days' },
{ label: conv({ hans: '1周', hant: '1週' }), value: '1 week' },
{ label: conv({ hans: '2周', hant: '2週' }), value: '2 weeks' },
{ label: conv({ hans: '1个月', hant: '1個月' }), value: '1 month' },
{ label: conv({ hans: '3个月', hant: '3個月' }), value: '3 months' },
{ label: conv({ hans: '6个月', hant: '6個月' }), value: '6 months' },
{ label: '1年', value: '1 year' },
{ label: '2年', value: '2 years' },
{ label: '3年', value: '3 years' }
]
});
field_block_options.append({
type: 'input',
name: 'expiry',
label: conv({ hans: '自定义过期时间', hant: '自訂過期時間' }),
tooltip: conv({ hans: '您可以使用相对时间,如“1 minute”或“19 days”;或绝对时间,“yyyymmddhhmm”(如“200602011405”是2006年2月1日14:05 UTC。)', hant: '您可以使用相對時間,如「1 minute」或「19 days」;或絕對時間,「yyyymmddhhmm」(如「200602011405」是2006年2月1日14:05 UTC。)' }),
value: Twinkle.block.field_block_options.expiry || Twinkle.block.field_template_options.template_expiry
});
if (partialBox) { // Partial block
field_block_options.append({
type: 'select',
multiple: true,
name: 'pagerestrictions',
label: conv({ hans: '页面封禁', hant: '頁面封鎖' }),
value: '',
tooltip: conv({ hans: '最多10个页面。', hant: '最多10個頁面。' })
});
var ns = field_block_options.append({
type: 'select',
multiple: true,
name: 'namespacerestrictions',
label: conv({ hans: '命名空间封禁', hant: '命名空間封鎖' }),
value: '',
tooltip: conv({ hans: '指定封禁的命名空间。', hant: '指定封鎖的命名空間。' })
});
$.each(menuFormattedNamespaces, function(number, name) {
// Ignore -1: Special; -2: Media; and 2300-2303: Gadget (talk) and Gadget definition (talk)
if (number >= 0 && number < 830) {
ns.append({ type: 'option', label: name, value: number });
}
});
}
var blockoptions = [
{
checked: Twinkle.block.field_block_options.nocreate,
label: conv({ hans: '禁止创建账户', hant: '禁止建立帳號' }),
name: 'nocreate',
value: '1'
},
{
checked: Twinkle.block.field_block_options.noemail,
label: conv({ hans: '电子邮件停用', hant: '電子郵件停用' }),
name: 'noemail',
value: '1'
},
{
checked: Twinkle.block.field_block_options.disabletalk,
label: conv({ hans: '不能编辑自己的讨论页', hant: '不能編輯自己的討論頁' }),
name: 'disabletalk',
value: '1',
tooltip: partialBox ? conv({ hans: '如果使用部分封禁,不应选择此项,除非您也想要禁止编辑用户讨论页。', hant: '如果使用部分封鎖,不應選擇此項,除非您也想要禁止編輯使用者討論頁。' }) : ''
}
];
if (Twinkle.block.isRegistered) {
blockoptions.push({
checked: Twinkle.block.field_block_options.autoblock,
label: conv({ hans: '自动封禁', hant: '自動封鎖' }),
name: 'autoblock',
value: '1'
});
} else {
blockoptions.push({
checked: Twinkle.block.field_block_options.hardblock,
label: conv({ hans: '阻止登录用户使用该IP地址编辑', hant: '阻止登入使用者使用該IP位址編輯' }),
name: 'hardblock',
value: '1'
});
}
blockoptions.push({
checked: Twinkle.block.field_block_options.watchuser,
label: conv({ hans: '监视该用户的用户页和讨论页', hant: '監視該使用者的使用者頁面和討論頁' }),
name: 'watchuser',
value: '1'
});
blockoptions.push({
checked: true,
label: conv({ hans: '标记当前的破坏中的请求', hant: '標記當前的破壞中的請求' }),
name: 'closevip',
value: '1'
});
field_block_options.append({
type: 'checkbox',
name: 'blockoptions',
list: blockoptions
});
field_block_options.append({
type: 'textarea',
label: conv({ hans: '理由(用于封禁日志):', hant: '理由(用於封鎖日誌):' }),
name: 'reason',
tooltip: conv({ hans: '请考虑在默认的消息中加入有用的详细信息。', hant: '請考慮在預設的訊息中加入有用的詳細資訊。' }),
value: Twinkle.block.field_block_options.reason
});
field_block_options.append({
type: 'div',
name: 'filerlog_label',
label: conv({ hans: '参见:', hant: '參見:' }),
style: 'display:inline-block;font-style:normal !important',
tooltip: conv({ hans: '在封禁理由中标清特殊情况以供其他管理员参考', hant: '在封鎖理由中標清特殊情況以供其他管理員參考' })
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '过滤器日志', hant: '過濾器日誌' }),
checked: false,
value: conv({ hans: '过滤器日志', hant: '過濾器日誌' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'deleted_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '已删除的编辑', hant: '已刪除的編輯' }),
checked: false,
value: conv({ hans: '已删除的编辑', hant: '已刪除的編輯' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '用户讨论页', hant: '使用者討論頁' }),
checked: false,
value: conv({ hans: '用户讨论页', hant: '使用者討論頁' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '过去的封禁记录', hant: '過去的封鎖記錄' }),
checked: false,
value: conv({ hans: '过去的封禁记录', hant: '過去的封鎖記錄' })
}
]
});
field_block_options.append({
type: 'checkbox',
name: 'filter_see_also',
event: Twinkle.block.callback.toggle_see_alsos,
style: 'display:inline-block; margin-right:5px',
list: [
{
label: conv({ hans: '跨维基贡献', hant: '跨維基貢獻' }),
checked: false,
value: conv({ hans: '跨维基贡献', hant: '跨維基貢獻' })
}
]
});
// Yet-another-logevents-doesn't-handle-ranges-well
if (blockedUserName === relevantUserName) {
field_block_options.append({ type: 'hidden', name: 'reblock', value: '1' });
}
}
if (templateBox) {
field_template_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '模板选项', hant: '模板選項' }), name: 'field_template_options' });
field_template_options.append({
type: 'select',
name: 'template',
label: conv({ hans: '选择讨论页模板:', hant: '選擇討論頁模板:' }),
event: Twinkle.block.callback.change_template,
list: Twinkle.block.callback.filtered_block_groups(blockGroup, true),
value: Twinkle.block.field_template_options.template
});
field_template_options.append({
type: 'input',
name: 'article',
label: conv({ hans: '链接页面', hant: '連結頁面' }),
value: '',
tooltip: conv({ hans: '可以随通知链接页面,例如破坏的目标。没有条目需要链接则请留空。', hant: '可以隨通知連結頁面,例如破壞的目標。沒有條目需要連結則請留空。' })
});
// Only visible if partial and not blocking
field_template_options.append({
type: 'input',
name: 'area',
label: conv({ hans: '封禁范围', hant: '封鎖範圍' }),
value: '',
tooltip: conv({ hans: '阻止用户编辑的页面或命名空间的可选说明。', hant: '阻止使用者編輯的頁面或命名空間的可選說明。' })
});
if (!blockBox) {
field_template_options.append({
type: 'input',
name: 'template_expiry',
label: '封禁期限:',
value: '',
tooltip: conv({ hans: '封禁时长,如24小时、2周、无限期等。', hant: '封鎖時長,如24小時、2週、無限期等。' })
});
}
field_template_options.append({
type: 'input',
name: 'block_reason',
label: conv({ hans: '“由于…您已被封禁”', hant: '「由於…您已被封鎖」' }),
tooltip: conv({ hans: '可选的理由,用于替换默认理由。只在常规封禁模板中有效。', hant: '可選的理由,用於替換預設理由。只在常規封鎖模板中有效。' }),
value: Twinkle.block.field_template_options.block_reason,
size: 60
});
if (blockBox) {
field_template_options.append({
type: 'checkbox',
name: 'blank_duration',
list: [
{
label: conv({ hans: '不在模板中包含封禁期限', hant: '不在模板中包含封鎖期限' }),
checked: Twinkle.block.field_template_options.blank_duration,
tooltip: conv({ hans: '模板将会显示“一段时间”而不是具体时长', hant: '模板將會顯示「一段時間」而不是具體時長' })
}
]
});
} else {
field_template_options.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '不能编辑自己的讨论页', hant: '不能編輯自己的討論頁' }),
name: 'notalk',
checked: Twinkle.block.field_template_options.notalk,
tooltip: conv({ hans: '用此在封禁模板中指明该用户编辑讨论页的权限已被移除', hant: '用此在封鎖模板中指明該使用者編輯討論頁的權限已被移除' })
},
{
label: conv({ hans: '不能发送电子邮件', hant: '不能傳送電子郵件' }),
name: 'noemail_template',
checked: Twinkle.block.field_template_options.noemail_template,
tooltip: conv({ hans: '用此在封禁模板中指明该用户发送电子邮件的权限已被移除', hant: '用此在封鎖模板中指明該使用者傳送電子郵件的權限已被移除' })
},
{
label: conv({ hans: '不能创建账户', hant: '不能建立帳號' }),
name: 'nocreate_template',
checked: Twinkle.block.field_template_options.nocreate_template,
tooltip: conv({ hans: '用此在封禁模板中指明该用户创建账户的权限已被移除', hant: '用此在封鎖模板中指明該使用者建立帳號的權限已被移除' })
}
]
});
}
var $previewlink = $('<a id="twinkleblock-preview-link">' + conv({ hans: '预览', hant: '預覽' }) + '</a>');
$previewlink.off('click').on('click', function() {
Twinkle.block.callback.preview($form[0]);
});
$previewlink.css({cursor: 'pointer'});
field_template_options.append({ type: 'div', id: 'blockpreview', label: [ $previewlink[0] ] });
field_template_options.append({ type: 'div', id: 'twinkleblock-previewbox', style: 'display: none' });
}
if (tagBox) {
field_tag_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '标记用户页', hant: '標記使用者頁面' }), name: 'field_tag_options' });
field_tag_options.append({
type: 'checkbox',
name: 'tag',
label: conv({ hans: '选择用户页模板:', hant: '選擇使用者頁面模板:' }),
list: [
{
label: '{{Blocked user}}:' + conv({ hans: '一般永久封禁', hant: '一般永久封鎖' }),
value: 'Blocked user'
},
{
label: '{{Sockpuppet}}:' + conv({ hans: '傀儡账户', hant: '傀儡帳號' }),
value: 'Sockpuppet',
subgroup: [
{
name: 'sppUsername',
type: 'input',
label: conv({ hans: '主账户用户名:', hant: '主帳號使用者名稱:' })
},
{
name: 'sppType',
type: 'select',
label: conv({ hans: '状态:', hant: '狀態:' }),
list: [
{ type: 'option', value: 'blocked', label: 'blocked - ' + conv({ hans: '仅依行为证据认定', hant: '僅依行為證據認定' }), selected: true },
{ type: 'option', value: 'proven', label: 'proven - ' + conv({ hans: '经傀儡调查确认', hant: '經傀儡調查確認' }) },
{ type: 'option', value: 'confirmed', label: 'confirmed - ' + conv({ hans: '经查核确认', hant: '經查核確認' }) }
]
},
{
name: 'sppEvidence',
type: 'input',
label: conv({ hans: '根据……确定:', hant: '根據……確定:' }),
tooltip: conv({ hans: '纯文字或是带[[]]的链接,例如:[[Special:固定链接/xxxxxxxx|用户查核]]', hant: '純文字或是帶[[]]的連結,例如:[[Special:固定链接/xxxxxxxx|用戶查核]]' })
}
]
},
{
label: '{{Sockpuppeteer|blocked}}:' + conv({ hans: '傀儡主账户', hant: '傀儡主帳號' }),
value: 'Sockpuppeteer',
subgroup: [
{
type: 'checkbox',
list: [
{
name: 'spmChecked',
value: 'spmChecked',
label: conv({ hans: '经用户查核确认', hant: '經使用者查核確認' })
}
]
},
{
name: 'spmEvidence',
type: 'input',
label: conv({ hans: '额外理由:', hant: '額外理由:' })
}
]
},
{
label: '{{Locked global account}}:' + conv({ hans: '全域锁定', hant: '全域鎖定' }),
value: 'Locked global account',
subgroup: [
{
type: 'checkbox',
list: [
{
name: 'lockBlocked',
value: 'lockBlocked',
label: conv({ hans: '亦被本地封禁', hant: '亦被本地封鎖' })
}
]
}
]
}
]
});
field_tag_options.append({
type: 'input',
name: 'category',
label: 'Category:……的維基用戶分身' + conv({ hans: '(主账户用户名)', hant: '(主帳號使用者名稱)' }), // no variant conversion for category name
tooltip: conv({ hans: '您通常应该使用{{Sockpuppet}}的主账户参数来产生分类,只有单独使用{{Locked global account}}才需填写此项。', hant: '您通常應該使用{{Sockpuppet}}的主帳號參數來產生分類,只有單獨使用{{Locked global account}}才需填寫此項。' })
});
}
if (unblockBox) {
field_unblock_options = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '解除封禁选项', hant: '解除封鎖選項' }), name: 'field_unblock_options' });
field_unblock_options.append({
type: 'textarea',
label: conv({ hans: '理由(用于封禁日志):', hant: '理由(用於封鎖日誌):' }),
name: 'reason',
value: Twinkle.block.field_unblock_options.reason
});
}
var oldfield;
if (field_preset) {
oldfield = $form.find('fieldset[name="field_preset"]')[0];
oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
} else {
$form.find('fieldset[name="field_preset"]').hide();
}
if (field_block_options) {
oldfield = $form.find('fieldset[name="field_block_options"]')[0];
oldfield.parentNode.replaceChild(field_block_options.render(), oldfield);
$form.find('fieldset[name="field_64"]').show();
$form.find('[name=pagerestrictions]').select2({
width: '100%',
placeholder: conv({ hans: '输入要阻止用户编辑的页面', hant: '輸入要阻止使用者編輯的頁面' }),
language: {
errorLoading: function() {
return conv({ hans: '搜索词汇不完整或无效', hant: '搜尋詞彙不完整或無效' });
}
},
maximumSelectionLength: 10, // Software limitation [[phab:T202776]]
minimumInputLength: 1, // prevent ajax call when empty
ajax: {
url: mw.util.wikiScript('api'),
dataType: 'json',
delay: 100,
data: function(params) {
var title = mw.Title.newFromText(params.term);
if (!title) {
return;
}
return {
action: 'query',
format: 'json',
list: 'allpages',
apfrom: title.title,
apnamespace: title.namespace,
aplimit: '10'
};
},
processResults: function(data) {
return {
results: data.query.allpages.map(function(page) {
var title = mw.Title.newFromText(page.title, page.ns).toText();
return {
id: title,
text: title
};
})
};
}
},
templateSelection: function(choice) {
return $('<a>').text(choice.text).attr({
href: mw.util.getUrl(choice.text),
target: '_blank'
});
}
});
$form.find('[name=namespacerestrictions]').select2({
width: '100%',
matcher: Morebits.select2.matchers.wordBeginning,
language: {
searching: Morebits.select2.queryInterceptor
},
templateResult: Morebits.select2.highlightSearchMatches,
placeholder: conv({ hans: '选择要禁止用户编辑的命名空间', hant: '選擇要禁止使用者編輯的命名空間' })
});
mw.util.addCSS(
// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
// Adjust font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }' +
// Remove black border
'.select2-container--default.select2-container--focus .select2-selection--multiple { border: 1px solid #aaa; }' +
// Make the tiny cross larger
'.select2-selection__choice__remove { font-size: 130%; }'
);
} else {
$form.find('fieldset[name="field_block_options"]').hide();
$form.find('fieldset[name="field_64"]').hide();
// Clear select2 options
$form.find('[name=pagerestrictions]').val(null).trigger('change');
$form.find('[name=namespacerestrictions]').val(null).trigger('change');
}
if (field_template_options) {
oldfield = $form.find('fieldset[name="field_template_options"]')[0];
oldfield.parentNode.replaceChild(field_template_options.render(), oldfield);
e.target.form.root.previewer = new Morebits.wiki.preview($(e.target.form.root).find('#twinkleblock-previewbox').last()[0]);
} else {
$form.find('fieldset[name="field_template_options"]').hide();
}
if (field_tag_options) {
oldfield = $form.find('fieldset[name="field_tag_options"]')[0];
oldfield.parentNode.replaceChild(field_tag_options.render(), oldfield);
} else {
$form.find('fieldset[name="field_tag_options"]').hide();
}
if (field_unblock_options) {
oldfield = $form.find('fieldset[name="field_unblock_options"]')[0];
oldfield.parentNode.replaceChild(field_unblock_options.render(), oldfield);
} else {
$form.find('fieldset[name="field_unblock_options"]').hide();
}
// Any block, including ranges
if (Twinkle.block.currentBlockInfo) {
// false for an ip covered by a range or a smaller range within a larger range;
// true for a user, single ip block, or the exact range for a range block
var sameUser = blockedUserName === relevantUserName;
Morebits.status.init($('div[name="currentblock"] span').last()[0]);
var statusStr = relevantUserName + '已被' + (Twinkle.block.currentBlockInfo.partial === '' ? conv({ hans: '部分封禁', hant: '部分封鎖' }) : conv({ hans: '全站封禁', hant: '全站封鎖' }));
// Range blocked
if (Twinkle.block.currentBlockInfo.rangestart !== Twinkle.block.currentBlockInfo.rangeend) {
if (sameUser) {
statusStr += conv({ hans: '(段封禁)', hant: '(段封鎖)' });
} else {
// zhwiki: Change order
// Link to the full range
var $rangeblockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: blockedUserName, type: 'block'}) + '">' + (Morebits.ip.get64(relevantUserName) === blockedUserName ? '/64' : blockedUserName) + '</a>)'));
statusStr += conv({ hans: '(位于', hant: '(位於' }) + $rangeblockloglink.html() + conv({ hans: '段封禁内)', hant: '段封鎖內)' });
}
}
if (Twinkle.block.currentBlockInfo.expiry === 'infinity') {
statusStr += conv({ hans: '(无限期)', hant: '(無限期)' });
} else if (new Morebits.date(Twinkle.block.currentBlockInfo.expiry).isValid()) {
statusStr += conv({ hans: '(终止于', hant: '(終止於' }) + new Morebits.date(Twinkle.block.currentBlockInfo.expiry).calendar('utc') + ')';
}
var infoStr = conv({ hans: '此表单将', hant: '此表單將' });
if (sameUser) {
infoStr += conv({ hans: '变更封禁', hant: '變更封鎖' });
if (Twinkle.block.currentBlockInfo.partial === undefined && partialBox) {
infoStr += conv({ hans: '为部分封禁', hant: '為部分封鎖' });
} else if (Twinkle.block.currentBlockInfo.partial === '' && !partialBox) {
infoStr += conv({ hans: '为全站封禁', hant: '為全站封鎖' });
}
infoStr += '。';
} else {
infoStr += conv({ hans: '加上额外的', hant: '加上額外的' }) + (partialBox ? '部分' : '') + conv({ hans: '封禁。', hant: '封鎖。' });
}
Morebits.status.warn(statusStr, infoStr);
// Default to the current block conditions on intial form generation
Twinkle.block.callback.update_form(e, Twinkle.block.currentBlockInfo);
}
// This is where T146628 really comes into play: a rangeblock will
// only return the correct block log if wgRelevantUserName is the
// exact range, not merely a funtional equivalent
if (Twinkle.block.hasBlockLog) {
// zhwiki: Add more details
var blockloginfo = [];
var $blockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', { action: 'view', page: relevantUserName, type: 'block' }) + '">' + conv({ hans: '封禁日志', hant: '封鎖日誌' }) + '</a>)'));
if (Twinkle.block.currentBlockInfo) {
blockloginfo.push(conv({ hans: '封禁详情', hant: '封鎖詳情' }));
} else {
var lastBlockAction = Twinkle.block.blockLog[0],
blockAction = lastBlockAction.action === 'unblock' ? Twinkle.block.blockLog[1] : lastBlockAction;
blockloginfo.push('此' + (Morebits.ip.isRange(relevantUserName) ? conv({ hans: 'IP范围', hant: 'IP範圍' }) : conv({ hans: '用户', hant: '使用者' })) + '曾在');
blockloginfo.push($('<b>' + new Morebits.date(blockAction.timestamp).calendar('utc') + '</b>')[0]);
blockloginfo.push('被' + blockAction.user + conv({ hans: '封禁', hant: '封鎖' }));
blockloginfo.push($('<b>' + Morebits.string.formatTime(blockAction.params.duration) + '</b>')[0]);
if (lastBlockAction.action === 'unblock') {
blockloginfo.push(',' + new Morebits.date(lastBlockAction.timestamp).calendar('utc') + '解封');
} else { // block or reblock
blockloginfo.push(',' + new Morebits.date(blockAction.params.expiry).calendar('utc') + conv({ hans: '过期', hant: '過期' }));
}
}
Morebits.status.init($('div[name="hasblocklog"] span').last()[0]);
Morebits.status.warn(blockloginfo, $blockloglink[0]);
}
// Make sure all the fields are correct based on initial defaults
if (blockBox) {
Twinkle.block.callback.change_preset(e);
} else if (templateBox) {
Twinkle.block.callback.change_template(e);
}
};
/*
* Keep alphabetized by key name, Twinkle.block.blockGroups establishes
* the order they will appear in the interface
*
* Block preset format, all keys accept only 'true' (omit for false) except where noted:
* <title of block template> : {
* autoblock: <autoblock any IP addresses used (for registered users only)>
* disabletalk: <disable user from editing their own talk page while blocked>
* expiry: <string - expiry timestamp, can include relative times like "5 months", "2 weeks" etc>
* forAnonOnly: <show block option in the interface only if the relevant user is an IP>
* forRegisteredOnly: <show block option in the interface only if the relevant user is registered>
* label: <string - label for the option of the dropdown in the interface (keep brief)>
* noemail: prevent the user from sending email through Special:Emailuser
* pageParam: <set if the associated block template accepts a page parameter>
* prependReason: <string - prepends the value of 'reason' to the end of the existing reason, namely for when revoking talk page access>
* nocreate: <block account creation from the user's IP (for anonymous users only)>
* nonstandard: <template does not conform to stewardship of WikiProject User Warnings and may not accept standard parameters>
* reason: <string - block rationale, as would appear in the block log,
* and the edit summary for when adding block template, unless 'summary' is set>
* reasonParam: <set if the associated block template accepts a reason parameter>
* sig: <string - set to ~~~~ if block template does not accept "true" as the value, or set null to omit sig param altogether>
* summary: <string - edit summary for when adding block template to user's talk page, if not set, 'reason' is used>
* suppressArticleInSummary: <set to suppress showing the article name in the edit summary, as with attack pages>
* templateName: <string - name of template to use (instead of key name), entry will be omitted from the Templates list.
* (e.g. use another template but with different block options)>
* useInitialOptions: <when preset is chosen, only change given block options, leave others as they were>
*
* WARNING: 'anononly' and 'allowusertalk' are enabled by default.
* To disable, set 'hardblock' and 'disabletalk', respectively
*/
Twinkle.block.blockPresetsInfo = {
'anonblock': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{anonblock}}',
sig: '~~~~'
},
'blocked proxy': {
expiry: '2 years',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
hardblock: true,
reason: '{{blocked proxy}}',
sig: null
},
'CheckUser block': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{CheckUser block}}',
sig: '~~~~'
},
'checkuserblock-account': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{checkuserblock-account}}',
sig: '~~~~'
},
'school block': {
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
nonstandard: true,
reason: '{{school block}}',
sig: '~~~~'
},
'range block': {
expiry: '1 week',
reason: '<!-- 請登入您的帳號,若無帳號,請閱讀 https://w.wiki/Jyi -->{{range block}}',
nocreate: true,
nonstandard: true,
forAnonOnly: true,
sig: '~~~~'
},
// uw-prefixed
'uw-3block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '违反[[WP:3RR|回退不过三原则]]', hant: '違反[[WP:3RR|回退不過三原則]]' }),
summary: conv({ hans: '封禁通知:违反[[WP:3RR|回退不过三原则]]', hant: '封鎖通知:違反[[WP:3RR|回退不過三原則]]' })
},
'uw-ablock': {
autoblock: true,
expiry: '1 day',
forAnonOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-adblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:SOAP|散发广告/宣传]]', hant: '[[WP:SOAP|散發廣告/宣傳]]' }),
summary: conv({ hans: '封禁通知:散发[[WP:SOAP|散发广告/宣传]]', hant: '封鎖通知:散發[[WP:SOAP|散發廣告/宣傳]]' }),
templateName: 'uw-block'
},
'uw-block': {
autoblock: true,
expiry: '1 day',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-blockindef': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知', hant: '封鎖通知' }),
suppressArticleInSummary: true
},
'uw-blocknotalk': {
disabletalk: true,
pageParam: true,
reasonParam: true,
summary: conv({ hans: '封禁通知:禁止编辑讨论页', hant: '封鎖通知:禁止編輯討論頁' }),
suppressArticleInSummary: true
},
'uw-copyrightblock': {
autoblock: true,
expiry: 'infinity',
nocreate: true,
pageParam: true,
reason: conv({ hans: '多次加入[[WP:COPYVIO|侵犯著作权]]的内容', hant: '多次加入[[WP:COPYVIO|侵犯著作權]]的內容' }),
summary: conv({ hans: '封禁通知:持续[[WP:COPYVIO|侵犯著作权]]', hant: '封鎖通知:持續[[WP:COPYVIO|侵犯著作權]]' }),
templateName: 'uw-blockindef'
},
'uw-dblock': {
autoblock: true,
nocreate: true,
reason: conv({ hans: '持续无故删除内容', hant: '持續無故刪除內容' }),
pageParam: true,
summary: conv({ hans: '封禁通知:持续[[WP:VAN|删除内容]]', hant: '封鎖通知:持續[[WP:VAN|刪除內容]]' })
},
'uw-hblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:骚扰|骚扰用户]]', hant: '[[WP:騷擾|騷擾使用者]]' }),
summary: conv({ hans: '封禁通知:[[WP:骚扰|骚扰]]其他用户', hant: '封鎖通知:[[WP:騷擾|騷擾]]其他使用者' }),
templateName: 'uw-block'
},
'uw-npblock': {
autoblock: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VAN|在条目中增加无意义文字]]', hant: '[[WP:VAN|在條目中增加無意義文字]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN|在条目中增加无意义文字]]', hant: '封鎖通知:[[WP:VAN|在條目中增加無意義文字]]' }),
templateName: 'uw-block'
},
'uw-pablock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reason: conv({ hans: '无礼的行为、[[WP:NPA|攻击别人]]', hant: '無禮的行為、[[WP:NPA|攻擊別人]]' }),
summary: conv({ hans: '封禁通知:无礼的行为、[[WP:NPA|人身攻击]]', hant: '封鎖通知:無禮的行為、[[WP:NPA|人身攻擊]]' }),
templateName: 'uw-block'
},
'uw-sblock': {
autoblock: true,
nocreate: true,
reason: conv({ hans: '不断加入[[Wikipedia:垃圾内容|垃圾链接]]', hant: '不斷加入[[Wikipedia:垃圾內容|垃圾連結]]' }),
summary: conv({ hans: '封禁通知:利用维基百科散发[[Wikipedia:垃圾内容|垃圾链接]]', hant: '封鎖通知:利用維基百科散發[[Wikipedia:垃圾內容|垃圾連結]]' })
},
'uw-soablock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:SOAP|散发广告/宣传]]', hant: '[[WP:SOAP|散發廣告/宣傳]]' }),
summary: conv({ hans: '封禁通知:仅[[WP:SOAP|散发广告/宣传]]', hant: '封鎖通知:僅[[WP:SOAP|散發廣告/宣傳]]' }),
templateName: 'uw-block'
},
'uw-sockblock': {
autoblock: true,
expiry: '1 week',
forRegisteredOnly: true,
nocreate: true,
reason: conv({ hans: '滥用[[WP:SOCK|多个账户]]', hant: '濫用[[WP:SOCK|多個帳號]]' }),
summary: conv({ hans: '封禁通知:滥用[[WP:SOCK|多个账户]]', hant: '封鎖通知:濫用[[WP:SOCK|多個帳號]]' }),
templateName: 'uw-block'
},
'uw-softerblock': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-softerblock}}<!-- ' + conv({ hans: '宣传性用户名、软封禁', hant: '宣傳性使用者名稱、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]暗示您的账户代表一个团体、组织或网站', hant: '封鎖通知:您的[[WP:U|使用者名稱]]暗示您的帳號代表一個團體、組織或網站' })
},
'uw-spamublock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reason: '{{uw-spamublock}}<!-- ' + conv({ hans: '宣传性用户名、宣传性编辑', hant: '宣傳性使用者名稱、宣傳性編輯' }) + ' -->',
summary: conv({ hans: '封禁通知:仅[[WP:SOAP|广告宣传]],同时您的用户名违反[[WP:U|用户名方针]]', hant: '封鎖通知:僅[[WP:SOAP|廣告宣傳]],同時您的使用者名稱違反[[WP:U|使用者名稱方針]]' })
},
'uw-ublock': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock}}<!-- ' + conv({ hans: '不当用户名、软封禁', hant: '不當使用者名稱、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的用户名违反[[WP:U|用户名方针]]', hant: '封鎖通知:您的使用者名稱違反[[WP:U|使用者名稱方針]]' })
},
'uw-ublock-double': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock-double}}<!-- ' + conv({ hans: '用户名与其他用户相似、软封禁', hant: '使用者名稱與其他使用者相似、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]与其他维基百科用户过于相似', hant: '封鎖通知:您的[[WP:U|使用者名稱]]與其他維基百科使用者過於相似' })
},
'uw-ucblock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '屡次增加没有[[WP:RS|可靠来源]]的资料', hant: '屢次增加沒有[[WP:RS|可靠來源]]的資料' }),
summary: conv({ hans: '封禁通知:屡次增加没有[[WP:RS|可靠来源]]的资料', hant: '封鎖通知:屢次增加沒有[[WP:RS|可靠來源]]的資料' }),
templateName: 'uw-block'
},
'uw-ublock-wellknown': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: '{{uw-ublock-wellknown}}<!-- ' + conv({ hans: '用户名与知名人物相似、软封禁', hant: '使用者名稱與知名人物相似、軟封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]与知名人物过于相似', hant: '封鎖通知:您的[[WP:U|使用者名稱]]與知名人物過於相似' })
},
'uw-uhblock-double': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reason: '{{uw-uhblock-double}}<!-- ' + conv({ hans: '用户名试图冒充其他用户、硬封禁', hant: '使用者名稱試圖冒充其他使用者、硬封鎖' }) + ' -->',
summary: conv({ hans: '封禁通知:您的[[WP:U|用户名]]试图冒充其他维基百科用户', hant: '封鎖通知:您的[[WP:U|使用者名稱]]試圖冒充其他維基百科使用者' })
},
'uw-ublock|误导': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|误导}}', hant: '{{uw-ublock|誤導}}' }),
summary: conv({ hans: '封禁通知:误导性用户名', hant: '封鎖通知:誤導性使用者名稱' })
},
'uw-ublock|宣传': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|宣传}}', hant: '{{uw-ublock|宣傳}}' }),
summary: conv({ hans: '封禁通知:宣传性用户名', hant: '封鎖通知:宣傳性使用者名稱' })
},
'uw-ublock|攻击|或侮辱性': {
expiry: 'infinity',
reason: conv({ hans: '{{uw-ublock|攻击|或侮辱性}}', hant: '{{uw-ublock|攻擊|或侮辱性}}' }),
summary: conv({ hans: '封禁通知:攻击或侮辱性用户名', hant: '封鎖通知:攻擊或侮辱性使用者名稱' })
},
'uw-ublock|混淆': {
expiry: 'infinity',
reason: '{{uw-ublock|混淆}}',
summary: conv({ hans: '封禁通知:令人混淆的用户名', hant: '封鎖通知:令人混淆的使用者名稱' })
},
'uw-vblock': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VAN|破坏]]', hant: '[[WP:VAN|破壞]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN|破坏]]', hant: '封鎖通知:[[WP:VAN|破壞]]' })
},
'uw-voablock': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
pageParam: true,
reason: conv({ hans: '[[WP:VOA|纯粹破坏]]', hant: '[[WP:VOA|純粹破壞]]' }),
summary: conv({ hans: '封禁通知:您的账户仅用于[[WP:VAN|破坏]]', hant: '封鎖通知:您的帳號僅用於[[WP:VAN|破壞]]' }),
templateName: 'uw-blockindef'
},
'Bot block message': {
expiry: 'infinity',
forRegisteredOnly: true,
reason: conv({ hans: '机器人故障', hant: '機器人故障' }),
summary: conv({ hans: '封禁通知:机器人故障', hant: '封鎖通知:機器人故障' }),
sig: '~~~~'
},
// zhwiki
'vcc-violation': {
autoblock: true,
expiry: '1 day',
nocreate: true,
pageParam: true,
reasonParam: true,
reason: conv({ hans: '[[WP:VAN#LANG|繁简破坏]]', hant: '[[WP:VAN#LANG|繁簡破壞]]' }),
summary: conv({ hans: '封禁通知:[[WP:VAN#LANG|无故替换繁简用字]]', hant: '封鎖通知:[[WP:VAN#LANG|無故替換繁簡用字]]' }),
templateName: 'uw-block'
},
'cross-wiki-van': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '跨维基项目破坏', hant: '跨維基項目破壞' }),
summary: conv({ hans: '封禁通知:跨维基项目[[WP:VAN|破坏]]', hant: '封鎖通知:跨維基項目[[WP:VAN|破壞]]' }),
templateName: 'uw-blockindef'
},
'point-block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reasonParam: true,
reason: conv({ hans: '[[WP:POINT|为了阐释观点而扰乱维基百科]]', hant: '[[WP:POINT|為了闡釋觀點而擾亂維基百科]]' }),
summary: conv({ hans: '封禁通知:[[WP:POINT|为了阐释观点而扰乱维基百科]]', hant: '封鎖通知:[[WP:POINT|為了闡釋觀點而擾亂維基百科]]' }),
templateName: 'uw-block'
},
'game-block': {
autoblock: true,
expiry: '1 day',
nocreate: true,
reasonParam: true,
reason: conv({ hans: '[[WP:GAME|游戏维基规则]]', hant: '[[WP:GAME|遊戲維基規則]]' }),
summary: conv({ hans: '封禁通知:[[WP:GAME|游戏维基规则]]', hant: '封鎖通知:[[WP:GAME|遊戲維基規則]]' }),
templateName: 'uw-block'
},
'sock-contribs-anon': {
autoblock: true,
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根据用户贡献确定', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根據使用者貢獻確定' }),
summary: conv({ hans: '封禁通知:[[WP:SOCK|使用其他IP地址绕过封禁]]', hant: '封鎖通知:[[WP:SOCK|使用其他IP位址繞過封鎖]]' }),
templateName: 'uw-ablock'
},
'sock-cu-anon': {
autoblock: true,
expiry: '1 week',
forAnonOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 用户查核确认', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 使用者查核確認' }),
summary: conv({ hans: '封禁通知:[[WP:SOCK|使用其他IP地址绕过封禁]]', hant: '封鎖通知:[[WP:SOCK|使用其他IP位址繞過封鎖]]' }),
templateName: 'uw-ablock'
},
'sock-contribs-reg': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根据用户贡献确定', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 根據使用者貢獻確定' }),
summary: conv({ hans: '封禁通知:确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]', hant: '封鎖通知:確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]' }),
templateName: 'uw-blockindef'
},
'sock-cu-reg': {
autoblock: true,
expiry: 'infinity',
forRegisteredOnly: true,
nocreate: true,
reasonParam: true,
reason: conv({ hans: '确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 用户查核确认', hant: '確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]] - 使用者查核確認' }),
summary: conv({ hans: '封禁通知:确认为[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]', hant: '封鎖通知:確認為[[WP:SOCK|傀儡]]或[[WP:MEAT|真人傀儡]]' }),
templateName: 'uw-blockindef'
},
// Begin partial block templates, accessed in Twinkle.block.blockGroupsPartial
'uw-pblock': {
autoblock: true,
expiry: '1 day',
nocreate: false,
pageParam: false,
reasonParam: true,
summary: conv({ hans: '封禁通知:您已被禁止编辑维基百科的部分区域', hant: '封鎖通知:您已被禁止編輯維基百科的部分區域' })
}
};
Twinkle.block.transformBlockPresets = function twinkleblockTransformBlockPresets() {
// zhwiki: Merge custom reason
$.each(Twinkle.getPref('customBlockReasonList'), function(_, item) {
var newKey = item.value + '|' + item.label;
Twinkle.block.blockPresetsInfo[newKey] = Object.assign(
{},
{
autoblock: true,
nocreate: true
},
Twinkle.block.blockPresetsInfo[item.value],
{
reason: item.label,
templateName: item.value
}
);
if (Twinkle.block.blockPresetsInfo[item.value] === undefined) {
Twinkle.block.blockPresetsInfo[item.value] = {
pageParam: true,
reasonParam: true,
custom: true
};
}
});
// supply sensible defaults
$.each(Twinkle.block.blockPresetsInfo, function(preset, settings) {
settings.summary = settings.summary || settings.reason;
settings.sig = settings.sig !== undefined ? settings.sig : 'yes';
settings.indefinite = settings.indefinite || Morebits.string.isInfinity(settings.expiry);
if (!Twinkle.block.isRegistered && settings.indefinite) {
settings.expiry = '1 day';
} else {
settings.expiry = settings.expiry || '1 day';
}
// zhwiki
if (!Twinkle.block.isRegistered && ['uw-block', 'uw-blockindef'].indexOf(settings.templateName) > -1) {
settings.templateName = 'uw-ablock';
}
Twinkle.block.blockPresetsInfo[preset] = settings;
});
};
// These are the groups of presets and defines the order in which they appear. For each list item:
// label: <string, the description that will be visible in the dropdown>
// value: <string, the key of a preset in blockPresetsInfo>
// meta: <boolean, show in templates only, zhwiki>
Twinkle.block.blockGroups = [
{
label: conv({ hans: '常见封禁理由', hant: '常見封鎖理由' }),
list: [
{ label: conv({ hans: '通用封禁(自定义理由)', hant: '通用封鎖(自訂理由)' }), value: 'uw-block' },
{ label: conv({ hans: '通用封禁(自定义理由) - IP', hant: '通用封鎖(自訂理由) - IP' }), value: 'uw-ablock' },
{ label: conv({ hans: '通用封禁(自定义理由) - 无限期', hant: '通用封鎖(自訂理由) - 無限期' }), value: 'uw-blockindef' },
{ label: conv({ hans: '破坏', hant: '破壞' }), value: 'uw-vblock', selected: true },
{ label: conv({ hans: '繁简破坏', hant: '繁簡破壞' }), value: 'vcc-violation' },
{ label: conv({ hans: '跨维基项目破坏', hant: '跨維基項目破壞' }), value: 'cross-wiki-van' },
{ label: conv({ hans: '纯粹破坏', hant: '純粹破壞' }), value: 'uw-voablock' },
{ label: conv({ hans: '不断加入垃圾链接', hant: '不斷加入垃圾連結' }), value: 'uw-sblock' },
{ label: conv({ hans: '散发广告/宣传', hant: '散發廣告/宣傳' }), value: 'uw-adblock' },
{ label: conv({ hans: '仅散发广告/宣传', hant: '僅散發廣告/宣傳' }), value: 'uw-soablock' },
{ label: conv({ hans: '违反回退不过三原则', hant: '違反回退不過三原則' }), value: 'uw-3block' },
{ label: conv({ hans: '无礼的行为、人身攻击', hant: '無禮的行為、人身攻擊' }), value: 'uw-pablock' },
{ label: conv({ hans: '骚扰用户', hant: '騷擾使用者' }), value: 'uw-hblock' },
{ label: conv({ hans: '为了阐释观点而扰乱维基百科', hant: '為了闡釋觀點而擾亂維基百科' }), value: 'point-block' },
{ label: conv({ hans: '游戏维基规则', hant: '遊戲維基規則' }), value: 'game-block' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 根据用户贡献确定', hant: '確認為傀儡或真人傀儡 - 根據使用者貢獻確定' }), value: 'sock-contribs-anon' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 用户查核确认', hant: '確認為傀儡或真人傀儡 - 使用者查核確認' }), value: 'sock-contribs-anon' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 根据用户贡献确定', hant: '確認為傀儡或真人傀儡 - 根據使用者貢獻確定' }), value: 'sock-contribs-reg' },
{ label: conv({ hans: '确认为傀儡或真人傀儡 - 用户查核确认', hant: '確認為傀儡或真人傀儡 - 使用者查核確認' }), value: 'sock-cu-reg' },
{ label: conv({ hans: '滥用多个账户', hant: '濫用多個帳號' }), value: 'uw-sockblock' },
{ label: conv({ hans: '屡次增加没有可靠来源的资料', hant: '屢次增加沒有可靠來源的資料' }), value: 'uw-ucblock' },
{ label: conv({ hans: '在条目中增加无意义文字', hant: '在條目中增加無意義文字' }), value: 'uw-npblock' },
{ label: conv({ hans: '无故删除内容', hant: '無故刪除內容' }), value: 'uw-dblock' },
{ label: conv({ hans: '多次加入侵犯著作权的内容', hant: '多次加入侵犯著作權的內容' }), value: 'uw-copyrightblock' },
{ label: conv({ hans: '机器人发生故障并必须紧急停止', hant: '機器人發生故障並必須緊急停止' }), value: 'Bot block message' },
{ label: conv({ hans: '禁止编辑讨论页', hant: '禁止編輯討論頁' }), value: 'uw-blocknotalk', meta: true }
]
},
{
custom: true,
label: conv({ hans: '自定义封禁理由', hant: '自訂封鎖理由' })
},
{
label: conv({ hans: '用户名封禁', hant: '使用者名稱封鎖' }),
list: [
{ label: conv({ hans: '宣传性用户名、宣传性编辑', hant: '宣傳性使用者名稱、宣傳性編輯' }), value: 'uw-spamublock' },
{ label: conv({ hans: '宣传性用户名、软封禁', hant: '宣傳性使用者名稱、軟封鎖' }), value: 'uw-softerblock' },
{ label: conv({ hans: '用户名与其他用户相似、软封禁', hant: '使用者名稱與其他使用者相似、軟封鎖' }), value: 'uw-ublock-double' },
{ label: conv({ hans: '不当用户名、软封禁', hant: '不當使用者名稱、軟封鎖' }), value: 'uw-ublock' },
{ label: conv({ hans: '用户名试图冒充其他用户、硬封禁', hant: '使用者名稱試圖冒充其他使用者、硬封鎖' }), value: 'uw-uhblock-double' },
{ label: conv({ hans: '用户名与知名人物相似、软封禁', hant: '使用者名稱與知名人物相似、軟封鎖' }), value: 'uw-ublock-wellknown' },
{ label: conv({ hans: '误导性用户名', hant: '誤導性使用者名稱' }), value: 'uw-ublock|误导' },
{ label: conv({ hans: '宣传性用户名', hant: '宣傳性使用者名稱' }), value: 'uw-ublock|宣传' },
{ label: conv({ hans: '攻击性用户名', hant: '攻擊性使用者名稱' }), value: 'uw-ublock|攻击|或侮辱性' },
{ label: conv({ hans: '混淆性用户名', hant: '混淆性使用者名稱' }), value: 'uw-ublock|混淆' }
]
},
{
label: '其他模板',
list: [
{ label: 'anonblock', value: 'anonblock', forAnonOnly: true },
{ label: 'range block', value: 'range block', forAnonOnly: true },
{ label: 'school block', value: 'school block', forAnonOnly: true },
{ label: 'blocked proxy', value: 'blocked proxy', forAnonOnly: true },
{ label: 'CheckUser block', value: 'CheckUser block', forAnonOnly: true },
{ label: 'checkuserblock-account', value: 'checkuserblock-account', forRegisteredOnly: true }
]
}
];
Twinkle.block.blockGroupsPartial = [
{
label: conv({ hans: '常见部分封禁理由', hant: '常見部分封鎖理由' }),
list: [
{ label: conv({ hans: '通用部分封禁(自定义理由)', hant: '通用部分封鎖(自訂理由)' }), value: 'uw-pblock', selected: true }
]
}
];
Twinkle.block.callback.filtered_block_groups = function twinkleblockCallbackFilteredBlockGroups(group, show_template) {
return $.map(group, function(blockGroup) {
// zhwiki: Add custom reason
if (blockGroup.custom) {
if (show_template) {
var templates = $.map(Twinkle.getPref('customBlockReasonList'), function(item) {
if (Twinkle.block.blockPresetsInfo[item.value].custom) {
return item.value;
}
});
templates = Morebits.array.uniq(templates);
blockGroup.list = $.map(templates, function(template) {
return {
label: conv({ hans: '自定义模板', hant: '自訂模板' }),
value: template
};
});
} else {
blockGroup.list = $.map(Twinkle.getPref('customBlockReasonList'), function(item) {
return {
label: item.label,
value: item.value + '|' + item.label
};
});
}
}
var list = $.map(blockGroup.list, function(blockPreset) {
// zhwiki
if (!show_template && blockPreset.meta) {
return;
}
switch (blockPreset.value) {
case 'range block':
if (!Morebits.ip.isRange(relevantUserName)) {
return;
}
blockPreset.selected = !Morebits.ip.get64(relevantUserName);
break;
default:
break;
}
var blockSettings = Twinkle.block.blockPresetsInfo[blockPreset.value];
var registrationRestrict;
if (blockSettings.forRegisteredOnly) {
registrationRestrict = Twinkle.block.isRegistered;
} else if (blockSettings.forAnonOnly) {
registrationRestrict = !Twinkle.block.isRegistered;
} else {
registrationRestrict = true;
}
if (!(blockSettings.templateName && show_template) && registrationRestrict) {
var templateName = blockSettings.templateName || blockPreset.value;
return {
label: (show_template ? '{{' + templateName + '}}: ' : '') + blockPreset.label,
value: blockPreset.value,
data: [{
name: 'template-name',
value: templateName
}],
selected: !!blockPreset.selected,
disabled: !!blockPreset.disabled
};
}
});
if (list.length) {
return {
label: blockGroup.label,
list: list
};
}
});
};
Twinkle.block.callback.change_preset = function twinkleblockCallbackChangePreset(e) {
var form = e.target.form, key = form.preset.value;
if (!key) {
return;
}
Twinkle.block.callback.update_form(e, Twinkle.block.blockPresetsInfo[key]);
if (form.template) {
form.template.value = Twinkle.block.blockPresetsInfo[key].templateName || key;
Twinkle.block.callback.change_template(e);
}
};
Twinkle.block.callback.change_expiry = function twinkleblockCallbackChangeExpiry(e) {
var expiry = e.target.form.expiry;
if (e.target.value === 'custom') {
Morebits.quickForm.setElementVisibility(expiry.parentNode, true);
} else {
Morebits.quickForm.setElementVisibility(expiry.parentNode, false);
expiry.value = e.target.value;
}
};
Twinkle.block.seeAlsos = [];
Twinkle.block.callback.toggle_see_alsos = function twinkleblockCallbackToggleSeeAlso() {
var reason = this.form.reason.value.replace(
new RegExp('(<!-- )(参见|參見)' + Twinkle.block.seeAlsos.join('、') + '( -->)'), ''
);
Twinkle.block.seeAlsos = Twinkle.block.seeAlsos.filter(function(el) {
return el !== this.value;
}.bind(this));
if (this.checked) {
Twinkle.block.seeAlsos.push(this.value);
}
var seeAlsoMessage = Twinkle.block.seeAlsos.join('、');
if (!Twinkle.block.seeAlsos.length) {
this.form.reason.value = reason;
} else {
this.form.reason.value = reason + '<!-- ' + conv({ hans: '参见', hant: '參見' }) + seeAlsoMessage + ' -->';
}
};
// zhwiki: No ds
Twinkle.block.callback.update_form = function twinkleblockCallbackUpdateForm(e, data) {
var form = e.target.form, expiry = data.expiry;
// don't override original expiry if useInitialOptions is set
if (!data.useInitialOptions) {
if (Date.parse(expiry)) {
expiry = new Date(expiry).toGMTString();
form.expiry_preset.value = 'custom';
} else {
form.expiry_preset.value = data.expiry || 'custom';
}
form.expiry.value = expiry;
if (form.expiry_preset.value === 'custom') {
Morebits.quickForm.setElementVisibility(form.expiry.parentNode, true);
} else {
Morebits.quickForm.setElementVisibility(form.expiry.parentNode, false);
}
}
// boolean-flipped options, more at [[mw:API:Block]]
data.disabletalk = data.disabletalk !== undefined ? data.disabletalk : false;
data.hardblock = data.hardblock !== undefined ? data.hardblock : false;
// disable autoblock if blocking a bot
if (Twinkle.block.userIsBot || /bot\b/i.test(relevantUserName)) {
data.autoblock = false;
}
$(form).find('[name=field_block_options]').find(':checkbox').each(function(i, el) {
// don't override original options if useInitialOptions is set
if (data.useInitialOptions && data[el.name] === undefined) {
return;
}
if (el.name === 'closevip') {
return;
}
var check = data[el.name] === '' || !!data[el.name];
$(el).prop('checked', check);
});
if (data.prependReason && data.reason) {
form.reason.value = data.reason + ';' + form.reason.value;
} else {
form.reason.value = data.reason || '';
}
// Clear and/or set any partial page or namespace restrictions
if (form.pagerestrictions) {
var $pageSelect = $(form).find('[name=pagerestrictions]');
var $namespaceSelect = $(form).find('[name=namespacerestrictions]');
// Respect useInitialOptions by clearing data when switching presets
// In practice, this will always clear, since no partial presets use it
if (!data.useInitialOptions) {
$pageSelect.val(null).trigger('change');
$namespaceSelect.val(null).trigger('change');
}
// Add any preset options; in practice, just used for prior block settings
if (data.restrictions) {
if (data.restrictions.pages && !$pageSelect.val().length) {
var pages = data.restrictions.pages.map(function(pr) {
return pr.title;
});
// since page restrictions use an ajax source, we
// short-circuit that and just add a new option
pages.forEach(function(page) {
if (!$pageSelect.find("option[value='" + $.escapeSelector(page) + "']").length) {
var newOption = new Option(page, page, true, true);
$pageSelect.append(newOption);
}
});
$pageSelect.val($pageSelect.val().concat(pages)).trigger('change');
}
if (data.restrictions.namespaces) {
$namespaceSelect.val($namespaceSelect.val().concat(data.restrictions.namespaces)).trigger('change');
}
}
}
};
Twinkle.block.callback.change_template = function twinkleblockcallbackChangeTemplate(e) {
var form = e.target.form, value = form.template.value, settings = Twinkle.block.blockPresetsInfo[value];
var blockBox = $(form).find('[name=actiontype][value=block]').is(':checked');
var partialBox = $(form).find('[name=actiontype][value=partial]').is(':checked');
var templateBox = $(form).find('[name=actiontype][value=template]').is(':checked');
// Block form is not present
if (!blockBox) {
if (settings.indefinite || settings.nonstandard) {
if (Twinkle.block.prev_template_expiry === null) {
Twinkle.block.prev_template_expiry = form.template_expiry.value || '';
}
form.template_expiry.parentNode.style.display = 'none';
form.template_expiry.value = 'infinity';
} else if (form.template_expiry.parentNode.style.display === 'none') {
if (Twinkle.block.prev_template_expiry !== null) {
form.template_expiry.value = Twinkle.block.prev_template_expiry;
Twinkle.block.prev_template_expiry = null;
}
form.template_expiry.parentNode.style.display = 'block';
}
if (Twinkle.block.prev_template_expiry) {
form.expiry.value = Twinkle.block.prev_template_expiry;
}
Morebits.quickForm.setElementVisibility(form.notalk.parentNode, !settings.nonstandard);
// Partial
Morebits.quickForm.setElementVisibility(form.noemail_template.parentNode, partialBox);
Morebits.quickForm.setElementVisibility(form.nocreate_template.parentNode, partialBox);
} else if (templateBox) { // Only present if block && template forms both visible
Morebits.quickForm.setElementVisibility(
form.blank_duration.parentNode,
!settings.indefinite && !settings.nonstandard
);
}
// Only particularly relevant if template form is present
Morebits.quickForm.setElementVisibility(form.article.parentNode, settings && !!settings.pageParam);
Morebits.quickForm.setElementVisibility(form.block_reason.parentNode, settings && !!settings.reasonParam);
// zhwiki: Apply reason from blockPresetsInfo
if (settings.reasonParam) {
form.block_reason.value = Twinkle.block.blockPresetsInfo[form.preset.value].reason || '';
} else {
form.block_reason.value = '';
}
// Partial block
Morebits.quickForm.setElementVisibility(form.area.parentNode, partialBox && !blockBox);
form.root.previewer.closePreview();
};
Twinkle.block.prev_template_expiry = null;
Twinkle.block.callback.preview = function twinkleblockcallbackPreview(form) {
var params = {
article: form.article.value,
blank_duration: form.blank_duration ? form.blank_duration.checked : false,
disabletalk: form.disabletalk.checked || (form.notalk ? form.notalk.checked : false),
expiry: form.template_expiry ? form.template_expiry.value : form.expiry.value,
hardblock: Twinkle.block.isRegistered ? form.autoblock.checked : form.hardblock.checked,
indefinite: Morebits.string.isInfinity(form.template_expiry ? form.template_expiry.value : form.expiry.value),
reason: form.block_reason.value,
template: form.template.value,
partial: $(form).find('[name=actiontype][value=partial]').is(':checked'),
pagerestrictions: $(form.pagerestrictions).val() || [],
namespacerestrictions: $(form.namespacerestrictions).val() || [],
noemail: form.noemail.checked || (form.noemail_template ? form.noemail_template.checked : false),
nocreate: form.nocreate.checked || (form.nocreate_template ? form.nocreate_template.checked : false),
area: form.area.value
};
var templateText = Twinkle.block.callback.getBlockNoticeWikitext(params);
form.previewer.beginRender(templateText, 'User_talk:' + relevantUserName + '/Wikitext'); // Force wikitext/correct username
};
Twinkle.block.callback.evaluate = function twinkleblockCallbackEvaluate(e) {
var params = Morebits.quickForm.getInputData(e.target);
var $form = $(e.target),
toBlock = $form.find('[name=actiontype][value=block]').is(':checked'),
toWarn = $form.find('[name=actiontype][value=template]').is(':checked'),
toPartial = $form.find('[name=actiontype][value=partial]').is(':checked'),
toTag = $form.find('[name=actiontype][value=tag]').is(':checked'),
toProtect = $form.find('[name=actiontype][value=protect]').is(':checked'),
toUnblock = $form.find('[name=actiontype][value=unblock]').is(':checked'),
blockoptions = {}, templateoptions = {}, unblockoptions = {};
Twinkle.block.callback.saveFieldset($form.find('[name=field_block_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_template_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_tag_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_unblock_options]'));
blockoptions = Twinkle.block.field_block_options;
unblockoptions = Twinkle.block.field_unblock_options;
var toClosevip = !!blockoptions.closevip;
templateoptions = Twinkle.block.field_template_options;
templateoptions.disabletalk = !!(templateoptions.disabletalk || blockoptions.disabletalk);
templateoptions.hardblock = !!blockoptions.hardblock;
// remove extraneous
delete blockoptions.expiry_preset;
delete blockoptions.closevip;
// Partial API requires this to be gone, not false or 0
if (toPartial) {
blockoptions.partial = templateoptions.partial = true;
}
templateoptions.pagerestrictions = $form.find('[name=pagerestrictions]').val() || [];
templateoptions.namespacerestrictions = $form.find('[name=namespacerestrictions]').val() || [];
// Format for API here rather than in saveFieldset
blockoptions.pagerestrictions = templateoptions.pagerestrictions.join('|');
blockoptions.namespacerestrictions = templateoptions.namespacerestrictions.join('|');
// use block settings as warn options where not supplied
templateoptions.summary = templateoptions.summary || blockoptions.reason;
templateoptions.expiry = templateoptions.template_expiry || blockoptions.expiry;
// zhwiki
templateoptions.preset = toBlock ? params.preset : null;
// Check tags
// Given an array of incompatible tags, check if we have two or more selected
var checkIncompatible = function(conflicts, extra) {
var count = conflicts.reduce(function(sum, tag) {
return sum += params.tag.indexOf(tag) !== -1;
}, 0);
if (count > 1) {
var message = conv({ hans: '请在以下标签中择一使用', hant: '請在以下標籤中擇一使用' }) + ':{{' + conflicts.join('}}、{{') + '}}。';
message += extra ? extra : '';
alert(message);
return true;
}
};
if (toTag) {
if (params.tag.length === 0) {
return alert(conv({ hans: '请至少选择一个用户页标记!', hant: '請至少選擇一個使用者頁面標記!' }));
}
if (checkIncompatible(['Blocked user', 'Sockpuppet'], conv({ hans: '{{Sockpuppet}}已涵盖{{Blocked user}}的功能。', hant: '{{Sockpuppet}}已涵蓋{{Blocked user}}的功能。' }))) {
return;
}
if (checkIncompatible(['Blocked user', 'Sockpuppeteer'], conv({ hans: '{{Sockpuppeteer}}已涵盖{{Blocked user}}的功能。', hant: '{{Sockpuppeteer}}已涵蓋{{Blocked user}}的功能。' }))) {
return;
}
if (checkIncompatible(['Blocked user', 'Locked global account'], conv({ hans: '请使用{{Locked global account}}的“亦被本地封禁”选项。', hant: '請使用{{Locked global account}}的「亦被本地封鎖」選項。' }))) {
return;
}
if (checkIncompatible(['Sockpuppet', 'Sockpuppeteer'], conv({ hans: '请从主账户和分身账户中选择一个。', hant: '請從主帳號和分身帳號中選擇一個。' }))) {
return;
}
if (params.tag.indexOf('Sockpuppet') > -1 && params.sppUsername.trim() === '') {
return alert(conv({ hans: '请提供傀儡账户的主账户用户名!', hant: '請提供傀儡帳號的主帳號使用者名稱!' }));
}
}
if (toBlock) {
if (blockoptions.partial) {
if (blockoptions.disabletalk && blockoptions.namespacerestrictions.indexOf('3') === -1) {
return alert(conv({ hans: '部分封禁无法阻止编辑自己的讨论页,除非也封禁了User talk命名空间!', hant: '部分封鎖無法阻止編輯自己的討論頁,除非也封鎖了User talk命名空間!' }));
}
if (!blockoptions.namespacerestrictions && !blockoptions.pagerestrictions) {
if (!blockoptions.noemail && !blockoptions.nocreate) { // Blank entries technically allowed [[phab:T208645]]
return alert(conv({ hans: '没有选择页面或命名空间,也没有停用电子邮件或禁止创建账户;请选择至少一个选项以应用部分封禁!', hant: '沒有選擇頁面或命名空間,也沒有停用電子郵件或禁止建立帳號;請選擇至少一個選項以應用部分封鎖!' }));
} else if (!confirm(conv({ hans: '您将要进行封禁,但没有阻止任何页面或命名空间的编辑,确定要继续?', hant: '您將要進行封鎖,但沒有阻止任何頁面或命名空間的編輯,確定要繼續?' }))) {
return;
}
}
}
if (!blockoptions.expiry) {
return alert(conv({ hans: '请提供过期时间!', hant: '請提供過期時間!' }));
} else if (Morebits.string.isInfinity(blockoptions.expiry) && !Twinkle.block.isRegistered) {
return alert(conv({ hans: '禁止无限期封禁IP地址!', hant: '禁止無限期封鎖IP位址!' }));
}
if (!blockoptions.reason) {
return alert(conv({ hans: '请提供封禁理由!', hant: '請提供封鎖理由!' }));
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var statusElement = new Morebits.status(conv({ hans: '执行封禁', hant: '執行封鎖' }));
blockoptions.action = 'block';
blockoptions.user = relevantUserName;
// boolean-flipped options
blockoptions.anononly = blockoptions.hardblock ? undefined : true;
blockoptions.allowusertalk = blockoptions.disabletalk ? undefined : true;
/*
Check if block status changed while processing the form.
There's a lot to consider here. list=blocks provides the
current block status, but there are at least two issues with
relying on it. First, the id doesn't update on a reblock,
meaning the individual parameters need to be compared. This
can be done roughly with JSON.stringify - we can thankfully
rely on order from the server, although sorting would be
fine if not - but falsey values are problematic and is
non-ideal. More importantly, list=blocks won't indicate if a
non-blocked user is blocked then unblocked. This should be
exceedingy rare, but regardless, we thus need to check
list=logevents, which has a nicely updating logid
parameter. We can't rely just on that, though, since it
doesn't account for blocks that have expired on their own.
As such, we use both. Using some ternaries, the logid
variables are false if there's no logevents, so if they
aren't equal we defintely have a changed entry (send
confirmation). If they are equal, then either the user was
never blocked (the block statuses will be equal, no
confirmation) or there's no new block, in which case either
a block expired (different statuses, confirmation) or the
same block is still active (same status, no confirmation).
*/
var query = {
format: 'json',
action: 'query',
list: 'blocks|logevents',
letype: 'block',
lelimit: 1,
letitle: 'User:' + blockoptions.user
};
// bkusers doesn't catch single IPs blocked as part of a range block
if (mw.util.isIPAddress(blockoptions.user, true)) {
query.bkip = blockoptions.user;
} else {
query.bkusers = blockoptions.user;
query.list += '|users';
query.usprop = 'groups';
query.ususers = blockoptions.user;
query.meta = 'tokens';
query.type = 'userrights';
}
api.get(query).then(function(data) {
var block = data.query.blocks[0];
// As with the initial data fetch, if an IP is blocked
// *and* rangeblocked, this would only grab whichever
// block is more recent, which would likely mean a
// mismatch. However, if the rangeblock is updated
// while filling out the form, this won't detect that,
// but that's probably fine.
if (data.query.blocks.length > 1 && block.user !== relevantUserName) {
block = data.query.blocks[1];
}
var logevents = data.query.logevents[0];
var user = data.query.users ? data.query.users[0] : null;
var logid = data.query.logevents.length ? logevents.logid : false;
if (logid !== Twinkle.block.blockLogId || !!block !== !!Twinkle.block.currentBlockInfo) {
var message = blockoptions.user + conv({ hans: '的封禁状态已被修改。', hant: '的封鎖狀態已被修改。' });
if (block) {
message += conv({ hans: '新状态:', hant: '新狀態:' });
} else {
message += conv({ hans: '最新日志:', hant: '最新日誌:' });
}
var logExpiry = '';
if (logevents.params.duration) {
if (logevents.params.duration === 'infinity') {
logExpiry = conv({ hans: '无限期', hant: '無限期' });
} else {
var expiryDate = new Morebits.date(logevents.params.expiry);
logExpiry += (expiryDate.isBefore(new Date()) ? conv({ hans: '过期于', hant: '過期於' }) : '直到') + expiryDate.calendar();
}
} else { // no duration, action=unblock, just show timestamp
logExpiry = '於' + new Morebits.date(logevents.timestamp).calendar();
}
message += '由' + logevents.user + conv({ hans: '以“', hant: '以「' }) + logevents.comment + conv({ hans: '”', hant: '」' }) +
blockActionText[logevents.action] + logExpiry + conv({ hans: ',你想要以你的设置变更封禁吗?', hant: ',你想要以你的設定變更封鎖嗎?' });
if (!confirm(message)) {
Morebits.status.info(conv({ hans: '执行封禁', hant: '執行封鎖' }), conv({ hans: '用户取消操作', hant: '使用者取消操作' }));
return;
}
blockoptions.reblock = 1; // Writing over a block will fail otherwise
}
var groupsCanBeRemoved = [
'autoreviewer',
'confirmed',
'eventparticipant',
'filemover',
'ipblock-exempt',
'massmessage-sender',
'patroller',
'rollbacker',
'templateeditor',
'transwiki'
];
var groupsToBeRemoved = [];
if (user && Morebits.string.isInfinity(blockoptions.expiry)) {
groupsToBeRemoved = user.groups.filter(function (group) {
return groupsCanBeRemoved.indexOf(group) > -1;
});
}
// execute block
blockoptions.tags = Twinkle.changeTags;
blockoptions.token = mw.user.tokens.get('csrfToken');
var mbApi = new Morebits.wiki.api(conv({ hans: '执行封禁', hant: '執行封鎖' }), blockoptions, function () {
statusElement.info('完成');
if (toWarn) {
Twinkle.block.callback.issue_template(templateoptions);
}
if (toClosevip) {
var vipPage = new Morebits.wiki.page('Wikipedia:当前的破坏', conv({ hans: '关闭请求', hant: '關閉請求' }));
vipPage.setFollowRedirect(true);
vipPage.setCallbackParameters(blockoptions);
vipPage.load(Twinkle.block.callback.closeRequest);
}
if (groupsToBeRemoved.length > 0) {
var rightStatusElement = new Morebits.status(conv({ hans: '移除权限', hant: '移除權限' }));
if (confirm(conv({ hans: '该用户有以下权限:', hant: '該使用者有以下權限:' }) + groupsToBeRemoved.join('、') + conv({ hans: ',您是否想要同时移除这些权限?', hant: ',您是否想要同時移除這些權限?' }))) {
var revokeOptions = {
action: 'userrights',
user: blockoptions.user,
remove: groupsToBeRemoved.join('|'),
reason: conv({ hans: '用户已被无限期封禁', hant: '使用者已被無限期封鎖' }),
token: data.query.tokens.userrightstoken,
tags: Twinkle.changeTags
};
var mrApi = new Morebits.wiki.api(conv({ hans: '移除权限', hant: '移除權限' }), revokeOptions, function () {
rightStatusElement.info('已移除' + groupsToBeRemoved.join('、'));
});
mrApi.post();
} else {
rightStatusElement.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
}
}
});
mbApi.post();
});
} else if (toWarn) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Twinkle.block.callback.issue_template(templateoptions);
}
if (toTag || toProtect) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var userPage = 'User:' + Morebits.wiki.flow.relevantUserName(true);
var wikipedia_page = new Morebits.wiki.page(userPage, conv({ hans: '标记或保护用户页', hant: '標記或保護使用者頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.block.callback.taguserpage);
}
if (toUnblock) {
if (!unblockoptions.reason) {
return alert(conv({ hans: '请提供解除封禁理由!', hant: '請提供解除封鎖理由!' }));
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
var unblockStatusElement = new Morebits.status(conv({ hans: '执行解除封禁', hant: '執行解除封鎖' }));
unblockoptions.action = 'unblock';
unblockoptions.user = Morebits.wiki.flow.relevantUserName(true);
// execute unblock
unblockoptions.tags = Twinkle.changeTags;
unblockoptions.token = mw.user.tokens.get('csrfToken');
var unblockMbApi = new Morebits.wiki.api(conv({ hans: '执行解除封禁', hant: '執行解除封鎖' }), unblockoptions, function () {
unblockStatusElement.info('完成');
});
unblockMbApi.post();
}
if (!toBlock && !toWarn && !toTag && !toProtect && !toUnblock) {
return alert(conv({ hans: '请给Twinkle点事做!', hant: '請給Twinkle點事做!' }));
}
};
Twinkle.block.callback.taguserpage = function twinkleblockCallbackTagUserpage(pageobj) {
var params = pageobj.getCallbackParameters();
var statelem = pageobj.getStatusElement();
if (params.actiontype.indexOf('tag') > -1) {
var tags = [];
params.tag.forEach(function(tag) {
var tagtext = '{{' + tag;
switch (tag) {
case 'Blocked user':
break;
case 'Sockpuppet':
tagtext += '\n| 1 = ' + params.sppUsername.trim();
tagtext += '\n| 2 = ' + params.sppType.trim();
if (params.sppEvidence.trim()) {
tagtext += '\n| evidence = ' + params.sppEvidence.trim();
}
tagtext += '\n| locked = no';
tagtext += '\n| notblocked = no';
tagtext += '\n';
break;
case 'Sockpuppeteer':
tagtext += '\n| 1 = blocked';
tagtext += '\n| checked = ' + (params.spmChecked ? 'yes' : '');
if (params.spmEvidence.trim()) {
tagtext += '\n| evidence = ' + params.spmEvidence.trim();
}
tagtext += '\n';
break;
case 'Locked global account':
if (params.lockBlocked) {
tagtext += '|blocked=yes';
}
break;
default:
return alert(conv({ hans: '未知的用户页模板!', hant: '未知的使用者頁面模板!' }));
}
tagtext += '}}';
tags.push(tagtext);
});
var text = tags.join('\n');
if (params.category) {
text += '\n[[Category:' + params.category.trim() + '的維基用戶分身]]';
}
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '标记被永久封禁的用户页', hant: '標記被永久封鎖的使用者頁面' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.save(function() {
Morebits.status.info(conv({ hans: '标记用户页', hant: '標記使用者頁面' }), '完成');
statelem.status(conv({ hans: '正在保护页面', hant: '正在保護頁面' }));
pageobj.load(Twinkle.block.callback.protectuserpage);
});
} else {
Twinkle.block.callback.protectuserpage(pageobj);
}
};
Twinkle.block.callback.protectuserpage = function twinkleblockCallbackProtectUserpage(pageobj) {
var params = pageobj.getCallbackParameters();
var statelem = pageobj.getStatusElement();
if (params.actiontype.indexOf('protect') > -1) {
if (pageobj.exists()) {
pageobj.setEditProtection('sysop', 'indefinite');
pageobj.setMoveProtection('sysop', 'indefinite');
} else {
pageobj.setCreateProtection('sysop', 'indefinite');
}
pageobj.setEditSummary(conv({ hans: '被永久封禁的用户页', hant: '被永久封鎖的使用者頁面' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.protect(function() {
Morebits.status.info(conv({ hans: '保护用户页', hant: '保護使用者頁面' }), pageobj.exists() ? conv({ hans: '已全保护', hant: '已全保護' }) : conv({ hans: '已白纸保护', hant: '已白紙保護' }));
statelem.info('全部完成');
});
} else {
statelem.info('全部完成');
}
};
Twinkle.block.callback.issue_template = function twinkleblockCallbackIssueTemplate(formData) {
// Use wgRelevantUserName to ensure the block template goes to a single IP and not to the
// "talk page" of an IP range (which does not exist)
var userTalkPage = 'User_talk:' + Morebits.wiki.flow.relevantUserName(true);
var params = $.extend(formData, {
messageData: Twinkle.block.blockPresetsInfo[formData.template],
usertalk_summary: Twinkle.block.blockPresetsInfo[formData.preset || formData.template].summary, // zhwiki
reason: Twinkle.block.field_template_options.block_reason,
disabletalk: Twinkle.block.field_template_options.notalk,
noemail: Twinkle.block.field_template_options.noemail_template,
nocreate: Twinkle.block.field_template_options.nocreate_template
});
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '完成,将在几秒后加载用户讨论页', hant: '完成,將在幾秒後載入使用者討論頁' });
Morebits.wiki.flow.check(userTalkPage, function () {
var flowpage = new Morebits.wiki.flow(userTalkPage, conv({ hans: '用户Flow讨论页留言', hant: '使用者Flow討論頁留言' }));
flowpage.setCallbackParameters(params);
Twinkle.block.callback.main_flow(flowpage);
}, function () {
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '用户讨论页修改', hant: '使用者討論頁修改' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.block.callback.main);
});
};
Twinkle.block.callback.closeRequest = function twinkleblockCallbackCloseRequest(vipPage) {
var params = vipPage.getCallbackParameters();
var text = vipPage.getPageText();
var statusElement = vipPage.getStatusElement();
var userName = Morebits.wiki.flow.relevantUserName(true);
var expiryText = Morebits.string.formatTime(params.expiry);
var comment = '{{Blocked|' + (Morebits.string.isInfinity(params.expiry) ? 'indef' : expiryText) + '}}。';
var requestList = text.split(/(?=\n===.+===\s*\n)/);
var found = false;
var hidename = false;
var vipRe = new RegExp('{{\\s*[Vv]andal\\s*\\|\\s*(1\\s*=\\s*)?' + Morebits.pageNameRegex(userName) + '\\s*(\\|\\s*hidename\\s*=[^|]+)?}}', 'm');
for (var i = 1; i < requestList.length; i++) {
if (vipRe.exec(requestList[i])) {
hidename = /\|\s*hidename\s*=[^|]+/.test(requestList[i]);
requestList[i] = requestList[i].trimRight();
var newText = requestList[i].replace(/^(\*\s*处理:)[ \t]*(<!-- 非管理員僅可標記已執行的封禁,針對提報的意見請放在下一行 -->)?[ \t]*$/m, '$1' + comment + '--~~~~');
if (requestList[i] === newText) {
newText = requestList[i] + '\n* 处理:' + comment + '--~~~~';
}
requestList[i] = newText + '\n';
found = true;
break;
}
}
if (!found) {
statusElement.warn(conv({ hans: '没有找到相关的请求', hant: '沒有找到相關的請求' }));
return;
}
text = requestList.join('');
var summary;
if (hidename) {
summary = conv({ hans: '标记为已处理', hant: '標記為已處理' });
} else {
summary = '/* ' + userName + ' */ ';
if (Morebits.string.isInfinity(params.expiry)) {
summary += conv({ hans: '不限期封禁', hant: '不限期封鎖' });
} else {
summary += conv({ hans: '封禁', hant: '封鎖' }) + expiryText;
}
}
vipPage.setEditSummary(summary);
vipPage.setChangeTags(Twinkle.changeTags);
vipPage.setPageText(text);
vipPage.save();
};
Twinkle.block.callback.getBlockNoticeWikitext = function(params) {
var text = '{{', settings = Twinkle.block.blockPresetsInfo[params.template];
if (!settings.nonstandard) {
text += 'subst:' + params.template;
if (params.article && settings.pageParam) {
text += '|page=' + params.article;
}
if (!/te?mp|^\s*$|min/.exec(params.expiry)) {
if (params.indefinite) {
text += '|indef=yes';
} else if (!params.blank_duration) { // zhwiki: No expiry checks
// Block template wants a duration, not date
text += '|time=' + Morebits.string.formatTime(params.expiry); // zhwiki: formatTime
}
}
if (!Twinkle.block.isRegistered && !params.hardblock) {
text += '|anon=yes';
}
if (params.reason) {
text += '|reason=' + params.reason;
}
if (params.disabletalk) {
text += '|notalk=yes';
}
// Currently, all partial block templates are "standard"
// Building the template, however, takes a fair bit of logic
if (params.partial) {
if (params.pagerestrictions.length || params.namespacerestrictions.length) {
var makeSentence = function (array) {
if (array.length < 3) {
return array.join('和');
}
var last = array.pop();
return array.join('、') + '和' + last;
};
text += '|area=某些';
if (params.pagerestrictions.length) {
text += '頁面(' + makeSentence(params.pagerestrictions.map(function(p) {
return '[[:' + p + ']]';
}));
text += params.namespacerestrictions.length ? ')和某些' : ')';
}
if (params.namespacerestrictions.length) {
// 1 => Talk, 2 => User, etc.
var namespaceNames = params.namespacerestrictions.map(function(id) {
return menuFormattedNamespaces[id];
});
text += conv({ hans: '[[Wikipedia:命名空间|命名空间]](', hant: '[[Wikipedia:命名空間|命名空間]](' }) + makeSentence(namespaceNames) + ')';
}
} else if (params.area) {
text += '|area=' + params.area;
} else {
if (params.noemail) {
text += '|email=yes';
}
if (params.nocreate) {
text += '|accountcreate=yes';
}
}
}
} else {
text += params.template;
}
if (settings.sig) {
text += '|sig=' + settings.sig;
}
return text + '}}';
};
Twinkle.block.callback.main = function twinkleblockcallbackMain(pageobj) {
var params = pageobj.getCallbackParameters(),
date = new Morebits.date(pageobj.getLoadTime()),
messageData = params.messageData,
text;
params.indefinite = Morebits.string.isInfinity(params.expiry);
if (Twinkle.getPref('blankTalkpageOnIndefBlock') && params.template !== 'uw-lblock' && params.indefinite) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '根据参数设置清空讨论页并为日期创建新2级标题', hant: '根據偏好設定清空討論頁並為日期建立新2級標題' }));
text = date.monthHeader() + '\n';
} else {
text = pageobj.getPageText();
var dateHeaderRegex = date.monthHeaderRegex(), dateHeaderRegexLast, dateHeaderRegexResult;
while ((dateHeaderRegexLast = dateHeaderRegex.exec(text)) !== null) {
dateHeaderRegexResult = dateHeaderRegexLast;
}
// If dateHeaderRegexResult is null then lastHeaderIndex is never checked. If it is not null but
// \n== is not found, then the date header must be at the very start of the page. lastIndexOf
// returns -1 in this case, so lastHeaderIndex gets set to 0 as desired.
var lastHeaderIndex = text.lastIndexOf('\n==') + 1;
if (text.length > 0) {
text += '\n\n';
}
if (!dateHeaderRegexResult || dateHeaderRegexResult.index !== lastHeaderIndex) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '未找到当月的二级标题,将创建新的', hant: '未找到當月的二級標題,將建立新的' }));
text += date.monthHeader() + '\n';
}
}
params.expiry = typeof params.template_expiry !== 'undefined' ? params.template_expiry : params.expiry;
text += Twinkle.block.callback.getBlockNoticeWikitext(params);
// build the edit summary
var summary = params.usertalk_summary; // zhwiki
if (messageData.suppressArticleInSummary !== true && params.article) {
summary += conv({ hans: ',于', hant: ',於' }) + '[[:' + params.article + ']]';
}
pageobj.setPageText(text);
pageobj.setEditSummary(summary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchBlockNotices'));
pageobj.save();
};
Twinkle.block.callback.main_flow = function twinkleblockcallbackMain(flowobj) {
var params = flowobj.getCallbackParameters();
params.indefinite = (/indef|infinity|never|\*|max/).test(params.expiry);
params.expiry = typeof params.template_expiry !== 'undefined' ? params.template_expiry : params.expiry;
var title = params.usertalk_summary;
var content = Twinkle.block.callback.getBlockNoticeWikitext(params, true);
flowobj.setTopic(title);
flowobj.setContent(content);
flowobj.newTopic();
};
Twinkle.addInitCallback(Twinkle.block, 'block');
})(jQuery);
// </nowiki>
35692362783ed37f234ff1f822feb40f5d728d8d
MediaWiki:Gadget-friendlywelcome.js
8
154
311
310
2024-08-03T04:07:19Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlywelcome.js: Welcome module
****************************************
* Mode of invocation: Tab ("Wel"), or from links on diff pages
* Active on: Any page with relevant user name (userspace,
* contribs, etc.) and diff pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.welcome = function friendlywelcome() {
if (mw.util.getParamValue('friendlywelcome')) {
if (mw.util.getParamValue('friendlywelcome') === 'auto') {
Twinkle.welcome.auto();
} else {
Twinkle.welcome.semiauto();
}
} else {
Twinkle.welcome.normal();
}
};
Twinkle.welcome.auto = function() {
if (mw.util.getParamValue('action') !== 'edit') {
// userpage not empty, aborting auto-welcome
return;
}
Twinkle.welcome.welcomeUser();
};
Twinkle.welcome.semiauto = function() {
Twinkle.welcome.callback(Morebits.wiki.flow.relevantUserName());
};
Twinkle.welcome.normal = function() {
if (mw.util.getParamValue('diff')) {
// check whether the contributors' talk pages exist yet
var $oList = $('#mw-diff-otitle2').find('span.mw-usertoollinks a.new.mw-usertoollinks-talk').first();
var $nList = $('#mw-diff-ntitle2').find('span.mw-usertoollinks a.new.mw-usertoollinks-talk').first();
if ($oList.length > 0 || $nList.length > 0) {
var spanTag = function(color, content) {
var span = document.createElement('span');
span.style.color = color;
span.appendChild(document.createTextNode(content));
return span;
};
var welcomeNode = document.createElement('strong');
var welcomeLink = document.createElement('a');
welcomeLink.appendChild(spanTag('Black', '['));
welcomeLink.appendChild(spanTag('Goldenrod', conv({ hans: '欢迎', hant: '歡迎' })));
welcomeLink.appendChild(spanTag('Black', ']'));
welcomeNode.appendChild(welcomeLink);
if ($oList.length > 0) {
var oHref = $oList.attr('href');
var oWelcomeNode = welcomeNode.cloneNode(true);
oWelcomeNode.firstChild.setAttribute('href', oHref + '&' + $.param({
friendlywelcome: Twinkle.getPref('quickWelcomeMode') === 'auto' ? 'auto' : 'norm',
vanarticle: Morebits.pageNameNorm
}));
$oList[0].parentNode.parentNode.appendChild(document.createTextNode(' '));
$oList[0].parentNode.parentNode.appendChild(oWelcomeNode);
}
if ($nList.length > 0) {
var nHref = $nList.attr('href');
var nWelcomeNode = welcomeNode.cloneNode(true);
nWelcomeNode.firstChild.setAttribute('href', nHref + '&' + $.param({
friendlywelcome: Twinkle.getPref('quickWelcomeMode') === 'auto' ? 'auto' : 'norm',
vanarticle: Morebits.pageNameNorm
}));
$nList[0].parentNode.parentNode.appendChild(document.createTextNode(' '));
$nList[0].parentNode.parentNode.appendChild(nWelcomeNode);
}
}
}
if (Morebits.wiki.flow.relevantUserName()) {
Twinkle.addPortletLink(function() {
Twinkle.welcome.callback(Morebits.wiki.flow.relevantUserName());
}, conv({ hans: '欢迎', hant: '歡迎' }), 'friendly-welcome', conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
}
};
Twinkle.welcome.welcomeUser = function welcomeUser() {
Morebits.status.init(document.getElementById('mw-content-text'));
$('#catlinks').remove();
var params = {
template: Twinkle.getPref('quickWelcomeTemplate'),
article: mw.util.getParamValue('vanarticle') || '',
mode: 'auto'
};
var userTalkPage = mw.config.get('wgFormattedNamespaces')[3] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '欢迎完成,将在几秒内刷新页面', hant: '歡迎完成,將在幾秒內重新整理頁面' });
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '编辑用户讨论页', hant: '編輯使用者討論頁' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.welcome.callbacks.main);
};
Twinkle.welcome.callback = function friendlywelcomeCallback(uid) {
if (uid === mw.config.get('wgUserName') && !confirm(conv({ hans: '您真的要欢迎您自己吗?', hant: '您真的要歡迎您自己嗎?' }))) {
return;
}
var Window = new Morebits.simpleWindow(600, 420);
Window.setTitle(conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '欢迎设置', hant: '歡迎設定' }), 'WP:TW/PREF#welcome');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'H:TW#欢迎');
var form = new Morebits.quickForm(Twinkle.welcome.callback.evaluate);
form.append({
type: 'select',
name: 'type',
label: conv({ hans: '欢迎类型:', hant: '歡迎類別:' }),
event: Twinkle.welcome.populateWelcomeList,
list: [
{ type: 'option', value: 'standard', label: conv({ hans: '标准欢迎', hant: '標準歡迎' }), selected: !mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName()) },
{ type: 'option', value: 'anonymous', label: conv({ hans: '欢迎IP用户', hant: '歡迎IP使用者' }), selected: mw.util.isIPAddress(Morebits.wiki.flow.relevantUserName()) },
{ type: 'option', value: 'nonChinese', label: conv({ hans: '非中文欢迎', hant: '非中文歡迎' }) }
]
});
form.append({
type: 'div',
id: 'welcomeWorkArea',
className: 'morebits-scrollbox'
});
form.append({
type: 'input',
name: 'article',
label: conv({ hans: '* 条目链接(如果模板支持):', hant: '* 條目連結(如果模板支援):' }),
value: mw.util.getParamValue('vanarticle') || '',
tooltip: conv({ hans: '如果模板支持则可以链接到条目,留空则不链接。支持链接的模板以星号标注。', hant: '如果模板支援則可以連結到條目,留空則不連結。支援連結的模板以星號標註。' })
});
// Only displayed when the user viewing the user talk page
if (mw.config.get('wgNamespaceNumber') === 3 && mw.config.get('wgTitle') === Morebits.wiki.flow.relevantUserName()) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '欢迎前清空用户讨论页', hant: '歡迎前清空使用者討論頁' }),
value: 'blank',
name: 'blank',
tooltip: conv({ hans: '适用于用户讨论页面上仅有胡言乱语或编辑测试时。', hant: '適用於使用者討論頁面上僅有胡言亂語或編輯測試時。' })
}
]
});
}
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.welcome.callbacks.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
form.append({ type: 'div', name: 'welcomepreview', label: [ previewlink ] });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// initialize the welcome list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.type.dispatchEvent(evt);
};
Twinkle.welcome.populateWelcomeList = function(e) {
var type = e.target.value;
var container = new Morebits.quickForm.element({ type: 'fragment' });
if ((type === 'standard' || type === 'anonymous') && Twinkle.getPref('customWelcomeList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义欢迎模板', hant: '自訂歡迎模板' }) });
container.append({
type: 'radio',
name: 'template',
list: Twinkle.getPref('customWelcomeList'),
event: function() {
e.target.form.article.disabled = false;
}
});
}
var sets = Twinkle.welcome.templates[type];
$.each(sets, function(label, templates) {
container.append({ type: 'header', label: label });
container.append({
type: 'radio',
name: 'template',
list: $.map(templates, function(properties, template) {
return {
value: template,
label: '{{' + template + '}}:' + properties.description + (properties.linkedArticle ? '\u00A0*' : ''), // U+00A0 NO-BREAK SPACE
tooltip: properties.tooltip // may be undefined
};
}),
event: function(ev) {
ev.target.form.article.disabled = !templates[ev.target.value].linkedArticle;
}
});
});
var rendered = container.render();
$(e.target.form).find('div#welcomeWorkArea').empty().append(rendered);
var firstRadio = e.target.form.template[0] || e.target.form.template;
firstRadio.checked = true;
var vals = sets[Object.keys(sets)[0]];
e.target.form.article.disabled = vals[firstRadio.value] ? !vals[firstRadio.value].linkedArticle : true;
};
// A list of welcome templates and their properties and syntax
// The four fields that are available are "description", "linkedArticle", "syntax", and "tooltip".
// The three magic words that can be used in the "syntax" field are:
// - $USERNAME$ - replaced by the welcomer's username, depending on user's preferences
// - $ARTICLE$ - replaced by an article name, if "linkedArticle" is true
// - $HEADER$ - adds a level 2 header (most templates already include this)
Twinkle.welcome.templates = {
standard: {
[conv({ hans: '一般欢迎模板', hant: '一般歡迎模板' })]: {
Welcome: {
description: conv({ hans: '标准欢迎', hant: '標準歡迎' }),
syntax: '{{subst:Welcome}}'
}
},
[conv({ hans: '问题用户欢迎模板', hant: '問題使用者歡迎模板' })]: {
Firstarticle: {
description: conv({ hans: '给第一篇条目不符条目创建指引的用户', hant: '給第一篇條目不符條目建立指引的使用者' }),
linkedArticle: true,
syntax: '{{subst:Firstarticle|1=$ARTICLE$}}'
}
}
},
anonymous: {
[conv({ hans: '匿名用户欢迎模板', hant: '匿名使用者歡迎模板' })]: {
Welcomeip: {
description: conv({ hans: '供匿名用户,鼓励其创建账户', hant: '供匿名使用者,鼓勵其建立帳戶' }),
syntax: '{{subst:Welcomeip}}'
}
}
},
nonChinese: {
[conv({ hans: '非中文欢迎模板', hant: '非中文歡迎模板' })]: {
Welcomeen: {
description: conv({ hans: '欢迎非中文用户', hant: '歡迎非中文使用者' }),
linkedArticle: true,
syntax: '{{subst:Welcomeen|art=$ARTICLE$}}'
}
}
}
};
/* eslint-enable quote-props */
Twinkle.welcome.getTemplateWikitext = function(type, template, article) {
// the iteration is required as the type=standard has two groups
var properties;
$.each(Twinkle.welcome.templates[type], function(label, templates) {
properties = templates[template];
if (properties) {
return false; // break
}
});
if (properties) {
return properties.syntax.
replace('$USERNAME$', Twinkle.getPref('insertUsername') ? mw.config.get('wgUserName') : '').
replace('$ARTICLE$', article ? article : '').
replace(/\$HEADER\$\s*/, '== ' + conv({ hans: '欢迎', hant: '歡迎' }) + ' ==\n\n').
replace('$EXTRA$', ''); // EXTRA is not implemented yet
}
return '{{subst:' + template + (article ? '|art=' + article : '') + '}}' +
(Twinkle.getPref('customWelcomeSignature') ? ' ~~~~' : '');
};
Twinkle.welcome.callbacks = {
preview: function(form) {
var previewDialog = new Morebits.simpleWindow(750, 400);
previewDialog.setTitle(conv({ hans: '预览欢迎模板', hant: '預覽歡迎模板' }));
previewDialog.setScriptName(conv({ hans: '欢迎用户', hant: '歡迎使用者' }));
previewDialog.setModality(true);
var previewdiv = document.createElement('div');
previewdiv.style.marginLeft = previewdiv.style.marginRight = '0.5em';
previewdiv.style.fontSize = 'small';
previewDialog.setContent(previewdiv);
var previewer = new Morebits.wiki.preview(previewdiv);
var input = Morebits.quickForm.getInputData(form);
previewer.beginRender(Twinkle.welcome.getTemplateWikitext(input.type, input.template, input.article), 'User talk:' + Morebits.wiki.flow.relevantUserName()); // Force wikitext/correct username
var submit = document.createElement('input');
submit.setAttribute('type', 'submit');
submit.setAttribute('value', conv({ hans: '关闭', hant: '關閉' }));
previewDialog.addContent(submit);
previewDialog.display();
$(submit).click(function() {
previewDialog.close();
});
},
main: function(pageobj) {
var params = pageobj.getCallbackParameters();
var text = pageobj.getPageText();
// abort if mode is auto and form is not empty
if (pageobj.exists() && params.mode === 'auto') {
Morebits.status.info('警告', conv({ hans: '用户讨论页不是空的,略过自动欢迎', hant: '使用者討論頁不是空的,略過自動歡迎' }));
Morebits.wiki.actionCompleted.event();
return;
}
var welcomeText = Twinkle.welcome.getTemplateWikitext(params.type, params.template, params.article);
if (params.blank) {
text = '';
}
if (Twinkle.getPref('topWelcomes')) {
text = welcomeText + '\n\n' + text;
} else {
text += '\n' + welcomeText;
}
var summaryText = conv({ hans: '欢迎来到维基百科!', hant: '歡迎來到維基百科!' });
pageobj.setPageText(text);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchWelcomes'));
pageobj.setCreateOption('recreate');
pageobj.save();
}
};
Twinkle.welcome.callback.evaluate = function friendlywelcomeCallbackEvaluate(e) {
var form = e.target;
var params = Morebits.quickForm.getInputData(form); // : type, template, article
params.mode = 'manual';
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var userTalkPage = mw.config.get('wgFormattedNamespaces')[3] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '欢迎完成,将在几秒内刷新讨论页面', hant: '歡迎完成,將在幾秒內重新整理討論頁面' });
var wikipedia_page = new Morebits.wiki.page(userTalkPage, conv({ hans: '修改用户讨论页', hant: '修改使用者討論頁' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.welcome.callbacks.main);
};
Twinkle.addInitCallback(Twinkle.welcome, 'welcome');
})(jQuery);
// </nowiki>
61091408bf8564378e22a5a932ca0c8850316f3f
MediaWiki:Gadget-friendlytalkback.js
8
155
313
312
2024-08-03T04:07:20Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlytalkback.js: Talkback module
****************************************
* Mode of invocation: Tab ("TB")
* Active on: Any page with relevant user name (userspace, contribs, etc.)
* Config directives in: FriendlyConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.talkback = function() {
if (!Morebits.wiki.flow.relevantUserName()) {
return;
}
Twinkle.addPortletLink(Twinkle.talkback.callback, '通告', 'friendly-talkback', conv({ hans: '回复通告', hant: '回覆通告' }));
};
Twinkle.talkback.callback = function() {
if (Morebits.wiki.flow.relevantUserName() === mw.config.get('wgUserName') && !confirm(conv({ hans: '您寂寞到了要自己通告自己的程度么?', hant: '您寂寞到了要自己通告自己的程度麼?' }))) {
return;
}
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '回复通告', hant: '回覆通告' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '关于{{talkback}}', hant: '關於{{talkback}}' }), 'Template:Talkback');
Window.addFooterLink(conv({ hans: '通告设置', hant: '通告設定' }), 'WP:TW/PREF#talkback');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#talkback');
var form = new Morebits.quickForm(Twinkle.talkback.evaluate);
form.append({ type: 'radio', name: 'tbtarget',
list: [
{
label: conv({ hans: '回复:我的讨论页', hant: '回覆:我的討論頁' }),
value: 'mytalk',
checked: 'true'
},
{
label: conv({ hans: '回复:其他用户的讨论页', hant: '回覆:其他使用者的討論頁' }),
value: 'usertalk'
},
{
label: conv({ hans: '回复:其它页面', hant: '回覆:其它頁面' }),
value: 'other'
},
{
label: conv({ hans: '邀请讨论', hant: '邀請討論' }),
value: 'see'
},
{
label: '通告板通知',
value: 'notice'
},
{
label: conv({ hans: '“有新邮件”', hant: '「有新郵件」' }),
value: 'mail'
}
],
event: Twinkle.talkback.changeTarget
});
form.append({
type: 'field',
label: '工作区',
name: 'work_area'
});
var previewlink = document.createElement('a');
$(previewlink).click(function() {
Twinkle.talkback.preview(result); // |result| is defined below
});
previewlink.style.cursor = 'pointer';
previewlink.textContent = conv({ hans: '预览', hant: '預覽' });
form.append({ type: 'div', id: 'talkbackpreview', label: [ previewlink ] });
form.append({ type: 'div', id: 'friendlytalkback-previewbox', style: 'display: none' });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
result.previewer = new Morebits.wiki.preview($(result).find('div#friendlytalkback-previewbox').last()[0]);
// We must init the
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.tbtarget[0].dispatchEvent(evt);
// Check whether the user has opted out from talkback
var query = {
action: 'query',
prop: 'extlinks',
titles: 'User talk:' + Morebits.wiki.flow.relevantUserName(),
elquery: 'userjs.invalid/noTalkback',
ellimit: '1'
};
var wpapi = new Morebits.wiki.api(conv({ hans: '抓取退出通告信息', hant: '抓取退出通告資訊' }), query, Twinkle.talkback.callback.optoutStatus);
wpapi.post();
};
Twinkle.talkback.optout = '';
Twinkle.talkback.callback.optoutStatus = function(apiobj) {
var $el = $(apiobj.getXML()).find('el');
if ($el.length) {
Twinkle.talkback.optout = Morebits.wiki.flow.relevantUserName() + conv({ hans: '不希望收到回复通告', hant: '不希望收到回覆通告' });
var url = $el.text();
var reason = mw.util.getParamValue('reason', url);
Twinkle.talkback.optout += reason ? ':' + Morebits.string.appendPunctuation(reason) : '。';
}
$('#twinkle-talkback-optout-message').text(Twinkle.talkback.optout);
};
var prev_page = '';
var prev_section = '';
var prev_message = '';
Twinkle.talkback.changeTarget = function(e) {
var value = e.target.values;
var root = e.target.form;
var old_area = Morebits.quickForm.getElements(root, 'work_area')[0];
if (root.section) {
prev_section = root.section.value;
}
if (root.message) {
prev_message = root.message.value;
}
if (root.page) {
prev_page = root.page.value;
}
var work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '回复通告信息', hant: '回覆通告資訊' }),
name: 'work_area'
});
root.previewer.closePreview();
switch (value) {
case 'mytalk':
/* falls through */
default:
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'usertalk':
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '用户(必填)', hant: '使用者(必填)' }),
tooltip: conv({ hans: '您留言页面的用户名,必填。', hant: '您留言頁面的使用者名稱,必填。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'notice':
var noticeboard = work_area.append({
type: 'select',
name: 'noticeboard',
label: '通告板:'
});
$.each(Twinkle.talkback.noticeboards, function(value, data) {
noticeboard.append({
type: 'option',
label: data.label,
value: value,
selected: !!data.defaultSelected
});
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '章节标题,留空则不会产生章节链接。', hant: '章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'other':
work_area.append({
type: 'div',
label: '',
style: 'color: red',
id: 'twinkle-talkback-optout-message'
});
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '完整页面名', hant: '完整頁面名' }),
tooltip: conv({ hans: '您留下消息的完整页面名,比如“Wikipedia talk:Twinkle”。', hant: '您留下訊息的完整頁面名,比如「Wikipedia talk:Twinkle」。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
case 'mail':
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '电子邮件主题(可选)', hant: '電子郵件主題(可選)' }),
tooltip: conv({ hans: '您发出的电子邮件的主题。', hant: '您發出的電子郵件的主題。' })
});
break;
case 'see':
work_area.append({
type: 'input',
name: 'page',
label: conv({ hans: '完整页面名', hant: '完整頁面名' }),
tooltip: conv({ hans: '您留下消息的完整页面名,比如“Wikipedia talk:Twinkle”。', hant: '您留下訊息的完整頁面名,比如「Wikipedia talk:Twinkle」。' }),
value: prev_page,
required: true
});
work_area.append({
type: 'input',
name: 'section',
label: conv({ hans: '章节(可选)', hant: '章節(可選)' }),
tooltip: conv({ hans: '您留言的章节标题,留空则不会产生章节链接。', hant: '您留言的章節標題,留空則不會產生章節連結。' }),
value: prev_section
});
break;
}
if (value !== 'notice') {
work_area.append({ type: 'textarea', label: conv({ hans: '附加信息(可选):', hant: '附加資訊(可選):' }), name: 'message', tooltip: conv({ hans: '会在回复通告模板下出现的消息,您的签名会被加在最后。', hant: '會在回覆通告模板下出現的訊息,您的簽名會被加在最後。' }) });
}
work_area = work_area.render();
root.replaceChild(work_area, old_area);
if (root.message) {
root.message.value = prev_message;
}
$('#twinkle-talkback-optout-message').text(Twinkle.talkback.optout);
};
Twinkle.talkback.noticeboards = {
affp: {
label: 'WP:AF/FP(' + conv({ hans: '防滥用过滤器/错误报告', hant: '防濫用過濾器/錯誤報告' }) + ')',
title: conv({ hans: '过滤器错误报告有新回应', hant: '過濾器錯誤報告有新回應' }),
content: conv({ hans: '您的[[Wikipedia:防滥用过滤器/错误报告|过滤器错误报告]]已有回应,请前往查看。', hant: '您的[[Wikipedia:防滥用过滤器/错误报告|過濾器錯誤報告]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[Wikipedia:防滥用过滤器/错误报告]]的通知', hant: '有關[[Wikipedia:防滥用过滤器/错误报告]]的通知' }),
defaultSelected: true
},
sbl: {
label: 'Spam-blacklist',
title: conv({ hans: '垃圾链接黑名单请求有新回应', hant: '垃圾連結黑名單請求有新回應' }),
content: conv({ hans: '您的[[MediaWiki talk:Spam-blacklist|垃圾链接黑名单请求]]已有回应,请前往查看。', hant: '您的[[MediaWiki talk:Spam-blacklist|垃圾連結黑名單請求]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[MediaWiki talk:Spam-blacklist]]的通知', hant: '有關[[MediaWiki talk:Spam-blacklist]]的通知' })
},
shl: {
label: 'Spam-whitelist',
title: conv({ hans: '垃圾链接白名单请求有新回应', hant: '垃圾連結白名單請求有新回應' }),
content: conv({ hans: '您的[[MediaWiki talk:Spam-whitelist|垃圾链接白名单请求]]已有回应,请前往查看。', hant: '您的[[MediaWiki talk:Spam-whitelist|垃圾連結白名單請求]]已有回應,請前往查看。' }) + '--~~~~',
editSummary: conv({ hans: '有关[[MediaWiki talk:Spam-whitelist]]的通知', hant: '有關[[MediaWiki talk:Spam-whitelist]]的通知' })
}
};
Twinkle.talkback.evaluate = function(e) {
var form = e.target;
var tbtarget = form.getChecked('tbtarget')[0];
var page, message;
var section = form.section.value;
var editSummary;
if (tbtarget === 'notice') {
page = form.noticeboard.value;
editSummary = Twinkle.talkback.noticeboards[page].editSummary;
} else {
// usertalk, other, see
page = form.page ? form.page.value : mw.config.get('wgUserName');
if (form.message) {
message = form.message.value.trim();
}
if (tbtarget === 'mail') {
editSummary = conv({ hans: '通知:有新邮件', hant: '通知:有新郵件' });
} else if (tbtarget === 'see') {
editSummary = conv({ hans: '请看看', hant: '請看看' }) + '[[:' + page + (section ? '#' + section : '') + ']]' + conv({ hans: '上的讨论', hant: '上的討論' });
} else { // tbtarget one of mytalk, usertalk, other
editSummary = conv({ hans: '回复通告', hant: '回覆通告' }) + '([[:';
if (tbtarget !== 'other' && !new RegExp('^\\s*' + Morebits.namespaceRegex(3) + ':', 'i').test(page)) {
editSummary += 'User talk:';
}
editSummary += page + (section ? '#' + section : '') + ']])';
}
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var fullUserTalkPageName = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user_talk] + ':' + Morebits.wiki.flow.relevantUserName();
Morebits.wiki.actionCompleted.redirect = fullUserTalkPageName;
Morebits.wiki.actionCompleted.notice = conv({ hans: '回复通告完成,将在几秒内刷新页面', hant: '回覆通告完成,將在幾秒內重新整理頁面' });
Morebits.wiki.flow.check(fullUserTalkPageName, function () {
var data = Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message);
var title = data[1], content = data[2];
var flowpage = new Morebits.wiki.flow(fullUserTalkPageName, conv({ hans: '加入回复通告', hant: '加入回覆通告' }));
flowpage.setTopic(title);
flowpage.setContent(content);
flowpage.newTopic();
}, function () {
var text = '\n\n' + Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message)[0];
var talkpage = new Morebits.wiki.page(fullUserTalkPageName, conv({ hans: '加入回复通告', hant: '加入回覆通告' }));
talkpage.setEditSummary(editSummary);
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setAppendText(text);
talkpage.setCreateOption('recreate');
talkpage.setMinorEdit(Twinkle.getPref('markTalkbackAsMinor'));
talkpage.setFollowRedirect(true);
talkpage.append();
});
};
Twinkle.talkback.preview = function(form) {
var tbtarget = form.getChecked('tbtarget')[0];
var section = form.section.value;
var page, message;
if (tbtarget === 'notice') {
page = form.noticeboard.value;
} else {
// usertalk, other, see
page = form.page ? form.page.value : mw.config.get('wgUserName');
if (form.message) {
message = form.message.value.trim();
}
}
var noticetext = Twinkle.talkback.getNoticeWikitext(tbtarget, page, section, message)[0];
form.previewer.beginRender(noticetext, 'User_talk:' + Morebits.wiki.flow.relevantUserName()); // Force wikitext/correct username
};
Twinkle.talkback.getNoticeWikitext = function(tbtarget, page, section, message) {
var text;
var title, content;
if (tbtarget === 'notice') {
title = Twinkle.talkback.noticeboards[page].title;
content = Morebits.string.safeReplace(Twinkle.talkback.noticeboards[page].content, '$SECTION', section);
text = '== ' + title + ' ==\n' + content;
} else if (tbtarget === 'see') {
title = page + conv({ hans: '的相关讨论', hant: '的相關討論' });
content = '{{subst:Please see|location=' + page + (section ? '#' + section : '') + '|more=' + message.trim() + '}}';
text = '{{subst:Please see|location=' + page + (section ? '#' + section : '') + '|more=' + message.trim() + '}}';
} else {
text = '==';
if (tbtarget === 'mail') {
title = Twinkle.getPref('mailHeading');
content = "{{You've got mail|subject=" + section + '|ts=~~~~~}}';
text += Twinkle.getPref('mailHeading') + '==\n' + "{{You've got mail|subject=" + section;
} else { // tbtarget one of mytalk, usertalk, other
// clean talkback heading: strip section header markers that were erroneously suggested in the documentation
title = Twinkle.getPref('talkbackHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, '$1');
content = '{{talkback|' + page + (section ? '|' + section : '');
text += Twinkle.getPref('talkbackHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, '$1') +
'==\n' + '{{talkback|' + page + (section ? '|' + section : '');
}
content += '|ts=~~~~~}}';
text += '|ts=~~~~~}}';
if (message) {
content += '\n' + message;
text += '\n' + message + ' ~~~~';
} else if (Twinkle.getPref('insertTalkbackSignature')) {
text += '\n~~~~';
}
}
return [text, title, content];
};
Twinkle.addInitCallback(Twinkle.talkback, 'talkback');
})(jQuery);
// </nowiki>
a2c30de6997bec15342227ae0ad6c382578c139e
MediaWiki:Gadget-twinklespeedy.js
8
156
315
314
2024-08-03T04:07:21Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklespeedy.js: CSD module
****************************************
* Mode of invocation: Tab ("CSD")
* Active on: Non-special, existing pages
*
* NOTE FOR DEVELOPERS:
* If adding a new criterion, add it to the appropriate places at the top of
* twinkleconfig.js. Also check out the default values of the CSD preferences
* in twinkle.js, and add your new criterion to those if you think it would be
* good.
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.speedy = function twinklespeedy() {
// Disable on:
// * special pages
// * Flow pages
// * non-existent pages
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
return;
}
Twinkle.addPortletLink(Twinkle.speedy.callback, conv({ hans: '速删', hant: '速刪' }), 'tw-csd', Morebits.userIsSysop ? conv({ hans: '快速删除', hant: '快速刪除' }) : conv({ hans: '请求快速删除', hant: '請求快速刪除' }));
};
// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
Twinkle.speedy.initDialog(Morebits.userIsSysop ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};
// Used by unlink feature
Twinkle.speedy.dialog = null;
// Used throughout
Twinkle.speedy.hasCSD = !!$('#delete-reason').length;
// The speedy criteria list can be in one of several modes
Twinkle.speedy.mode = {
sysopSingleSubmit: 1, // radio buttons, no subgroups, submit when "Submit" button is clicked
sysopRadioClick: 2, // radio buttons, no subgroups, submit when a radio button is clicked
sysopMultipleSubmit: 3, // check boxes, subgroups, "Submit" button already present
sysopMultipleRadioClick: 4, // check boxes, subgroups, need to add a "Submit" button
userMultipleSubmit: 5, // check boxes, subgroups, "Submit" button already pressent
userMultipleRadioClick: 6, // check boxes, subgroups, need to add a "Submit" button
userSingleSubmit: 7, // radio buttons, subgroups, submit when "Submit" button is clicked
userSingleRadioClick: 8, // radio buttons, subgroups, submit when a radio button is clicked
// are we in "delete page" mode?
// (sysops can access both "delete page" [sysop] and "tag page only" [user] modes)
isSysop: function twinklespeedyModeIsSysop(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
},
// do we have a "Submit" button once the form is created?
hasSubmitButton: function twinklespeedyModeHasSubmitButton(mode) {
return mode === Twinkle.speedy.mode.sysopSingleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick ||
mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.userSingleSubmit;
},
// is db-multiple the outcome here?
isMultiple: function twinklespeedyModeIsMultiple(mode) {
return mode === Twinkle.speedy.mode.userMultipleSubmit ||
mode === Twinkle.speedy.mode.sysopMultipleSubmit ||
mode === Twinkle.speedy.mode.userMultipleRadioClick ||
mode === Twinkle.speedy.mode.sysopMultipleRadioClick;
}
};
// Prepares the speedy deletion dialog and displays it
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
var dialog;
Twinkle.speedy.dialog = new Morebits.simpleWindow(Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight'));
dialog = Twinkle.speedy.dialog;
dialog.setTitle(conv({ hans: '选择快速删除理由', hant: '選擇快速刪除理由' }));
dialog.setScriptName('Twinkle');
dialog.addFooterLink(conv({ hans: '快速删除方针', hant: '快速刪除方針' }), 'WP:CSD');
dialog.addFooterLink(conv({ hans: '常见错误', hant: '常見錯誤' }), 'Wikipedia:管理员错误自查表/快速删除');
dialog.addFooterLink(conv({ hans: '速删设置', hant: '速刪設定' }), 'WP:TW/PREF#speedy');
dialog.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#speedy');
var form = new Morebits.quickForm(callbackfunc, Twinkle.getPref('speedySelectionStyle') === 'radioClick' ? 'change' : null);
if (Morebits.userIsSysop) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '只标记,不删除', hant: '只標記,不刪除' }),
value: 'tag_only',
name: 'tag_only',
tooltip: conv({ hans: '如果您只想标记此页面而不是将其删除', hant: '如果您只想標記此頁面而不是將其刪除' }),
checked: !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToDelete')),
event: function(event) {
var cForm = event.target.form;
var cChecked = event.target.checked;
// enable/disable talk page checkbox
if (cForm.talkpage) {
cForm.talkpage.disabled = cChecked;
cForm.talkpage.checked = !cChecked && Twinkle.getPref('deleteTalkPageOnDelete');
}
// enable/disable redirects checkbox
cForm.redirects.disabled = cChecked;
cForm.redirects.checked = !cChecked;
// enable/disable delete multiple
cForm.delmultiple.disabled = cChecked;
cForm.delmultiple.checked = false;
// enable/disable open talk page checkbox
cForm.openusertalk.disabled = cChecked;
cForm.openusertalk.checked = false;
// enable/disable notify checkbox
cForm.notify.disabled = !cChecked;
cForm.notify.checked = cChecked;
// enable/disable multiple
cForm.multiple.disabled = !cChecked;
cForm.multiple.checked = false;
// enable requesting creation protection
cForm.salting.checked = false;
Twinkle.speedy.callback.modeChanged(cForm);
event.stopPropagation();
}
}
]
});
var deleteOptions = form.append({
type: 'div',
name: 'delete_options'
});
deleteOptions.append({
type: 'header',
label: conv({ hans: '删除相关选项', hant: '刪除相關選項' })
});
if (mw.config.get('wgNamespaceNumber') % 2 === 0 && mw.config.get('wgNamespaceNumber') !== 2) { // hide option for user pages, to avoid accidentally deleting user talk page
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除讨论页', hant: '刪除討論頁' }),
value: 'talkpage',
name: 'talkpage',
tooltip: conv({ hans: '删除时附带删除此页面的讨论页。', hant: '刪除時附帶刪除此頁面的討論頁。' }),
checked: Twinkle.getPref('deleteTalkPageOnDelete'),
event: function(event) {
event.stopPropagation();
}
}
]
});
}
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除重定向', hant: '刪除重新導向' }),
value: 'redirects',
name: 'redirects',
tooltip: conv({ hans: '删除到此页的重定向。', hant: '刪除到此頁的重新導向。' }),
checked: Twinkle.getPref('deleteRedirectsOnDelete'),
event: function(event) {
event.stopPropagation();
}
}
]
});
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '应用多个理由删除', hant: '應用多個理由刪除' }),
value: 'delmultiple',
name: 'delmultiple',
tooltip: conv({ hans: '您可选择应用于该页的多个理由。', hant: '您可選擇應用於該頁的多個理由。' }),
event: function(event) {
Twinkle.speedy.callback.modeChanged(event.target.form);
event.stopPropagation();
}
}
]
});
deleteOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '开启用户讨论页', hant: '開啟使用者討論頁' }),
value: 'openusertalk',
name: 'openusertalk',
tooltip: conv({ hans: '此项的默认值为您的开启讨论页设置。在您选择应用多条理由删除时此项将保持不变。', hant: '此項的預設值為您的開啟討論頁設定。在您選擇應用多條理由刪除時此項將保持不變。' }),
checked: false
}
]
});
}
var tagOptions = form.append({
type: 'div',
name: 'tag_options'
});
if (Morebits.userIsSysop) {
tagOptions.append({
type: 'header',
label: conv({ hans: '标记相关选项', hant: '標記相關選項' })
});
}
tagOptions.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,通知创建者', hant: '如可能,通知建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '一个通知模板将会被加入创建者的讨论页,如果您启用了该理据的通知。', hant: '一個通知模板將會被加入建立者的討論頁,如果您啟用了該理據的通知。' }),
checked: !Morebits.userIsSysop || !(Twinkle.speedy.hasCSD || Twinkle.getPref('deleteSysopDefaultToDelete')),
event: function(event) {
event.stopPropagation();
}
},
{
label: conv({ hans: '清空页面', hant: '清空頁面' }),
value: 'blank',
name: 'blank',
tooltip: conv({ hans: '在标记模板前,先清空页面,适用于严重破坏或负面生者传记等。', hant: '在標記模板前,先清空頁面,適用於嚴重破壞或負面生者傳記等。' })
},
{
label: conv({ hans: '同时标记以请求白纸保护', hant: '同時標記以請求白紙保護' }),
value: 'salting',
name: 'salting',
tooltip: conv({ hans: '选取后,快速删除模板后将附带 {{salt}} 标签,以请求执行删除的管理员进行白纸保护,仅在页面创建3次以上才选择此项。', hant: '選取後,快速刪除模板後將附帶 {{salt}} 標籤,以請求執行刪除的管理員進行白紙保護,僅在頁面建立3次以上才選擇此項。' })
},
{
label: conv({ hans: '应用多个理由', hant: '應用多個理由' }),
value: 'multiple',
name: 'multiple',
tooltip: conv({ hans: '您可选择应用于该页的多个理由。', hant: '您可選擇應用於該頁的多個理由。' }),
event: function(event) {
Twinkle.speedy.callback.modeChanged(event.target.form);
event.stopPropagation();
}
}
]
});
form.append({
type: 'div',
id: 'prior-deletion-count'
});
form.append({
type: 'div',
name: 'work_area',
label: conv({ hans: '初始化CSD模块失败,请重试,或将这报告给Twinkle开发者。', hant: '初始化CSD模組失敗,請重試,或將這報告給Twinkle開發者。' })
});
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
form.append({ type: 'submit', className: 'tw-speedy-submit' }); // Renamed in modeChanged
}
var result = form.render();
dialog.setContent(result);
dialog.display();
Twinkle.speedy.callback.modeChanged(result);
// Check for prior deletions. Just once, upon init
Twinkle.speedy.callback.priorDeletionCount();
};
Twinkle.speedy.callback.getMode = function twinklespeedyCallbackGetMode(form) {
var mode = Twinkle.speedy.mode.userSingleSubmit;
if (form.tag_only && !form.tag_only.checked) {
if (form.delmultiple.checked) {
mode = Twinkle.speedy.mode.sysopMultipleSubmit;
} else {
mode = Twinkle.speedy.mode.sysopSingleSubmit;
}
} else {
if (form.multiple.checked) {
mode = Twinkle.speedy.mode.userMultipleSubmit;
} else {
mode = Twinkle.speedy.mode.userSingleSubmit;
}
}
if (Twinkle.getPref('speedySelectionStyle') === 'radioClick') {
mode++;
}
return mode;
};
Twinkle.speedy.callback.modeChanged = function twinklespeedyCallbackModeChanged(form) {
var namespace = mw.config.get('wgNamespaceNumber');
// first figure out what mode we're in
var mode = Twinkle.speedy.callback.getMode(form);
var isSysopMode = Twinkle.speedy.mode.isSysop(mode);
if (isSysopMode) {
$('[name=delete_options]').show();
$('[name=tag_options]').hide();
$('button.tw-speedy-submit').text(conv({ hans: '删除页面', hant: '刪除頁面' }));
} else {
$('[name=delete_options]').hide();
$('[name=tag_options]').show();
$('button.tw-speedy-submit').text(conv({ hans: '标记页面', hant: '標記頁面' }));
}
var work_area = new Morebits.quickForm.element({
type: 'div',
name: 'work_area'
});
if (mode === Twinkle.speedy.mode.userMultipleRadioClick || mode === Twinkle.speedy.mode.sysopMultipleRadioClick) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
work_area.append({
type: 'div',
label: conv({ hans: '当选择完成后,单击:', hant: '當選擇完成後,點擊:' })
});
work_area.append({
type: 'button',
name: 'submit-multiple',
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: function(event) {
Twinkle.speedy.callback[evaluateType](event);
event.stopPropagation();
}
});
}
var radioOrCheckbox = Twinkle.speedy.mode.isMultiple(mode) ? 'checkbox' : 'radio';
if (isSysopMode && !Twinkle.speedy.mode.isMultiple(mode)) {
work_area.append({ type: 'header', label: conv({ hans: '自定义理由', hant: '自訂理由' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.customRationale, mode) });
}
switch (namespace) {
case 0: // article and pseudo namespace
work_area.append({ type: 'header', label: conv({ hans: '条目', hant: '條目' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.articleList, mode) });
if (/^(MOS|LTA):/.test(mw.config.get('wgPageName')) && !Morebits.isPageRedirect()) { // pseudo namespace
work_area.append({ type: 'header', label: conv({ hans: '伪命名空间', hant: '偽命名空間' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.pseudoNSList, mode) });
}
break;
case 2: // user
work_area.append({ type: 'header', label: conv({ hans: '用户页', hant: '使用者頁面' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.userList, mode) });
break;
case 3: // user talk
if (mw.util.isIPAddress(mw.config.get('wgRelevantUserName'))) {
work_area.append({ type: 'header', label: conv({ hans: '用户讨论页', hant: '使用者討論頁' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.usertalkList, mode) });
}
break;
case 6: // file
work_area.append({ type: 'header', label: conv({ hans: '文件', hant: '檔案' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.fileList, mode) });
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append({ type: 'div', label: conv({ hans: '标记CSD F3、F4、F6、F8、F9、F10,请使用Twinkle的“图权”功能。', hant: '標記CSD F3、F4、F6、F8、F9、F10,請使用Twinkle的「圖權」功能。' }) });
}
break;
case 14: // category
work_area.append({ type: 'header', label: conv({ hans: '分类', hant: '分類' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.categoryList, mode) });
break;
case 118: // draft
work_area.append({ type: 'header', label: '草稿' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.draftList, mode) });
break;
default:
break;
}
// custom rationale lives under general criteria when tagging
var generalCriteria = Twinkle.speedy.generalList;
if (!Twinkle.speedy.mode.isSysop(mode)) {
generalCriteria = Twinkle.speedy.customRationale.concat(generalCriteria);
}
work_area.append({ type: 'header', label: conv({ hans: '常规', hant: '常規' }) });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(generalCriteria, mode) });
if (!Twinkle.speedy.mode.isSysop(mode)) {
work_area.append({ type: 'div', label: conv({ hans: '标记CSD G16,请使用Twinkle的“侵权”功能。', hant: '標記CSD G16,請使用Twinkle的「侵權」功能。' }) });
}
if (mw.config.get('wgIsRedirect') || Morebits.userIsSysop) {
work_area.append({ type: 'header', label: '重定向' });
work_area.append({ type: radioOrCheckbox, name: 'csd', list: Twinkle.speedy.generateCsdList(Twinkle.speedy.redirectList, mode) });
}
var old_area = Morebits.quickForm.getElements(form, 'work_area')[0];
form.replaceChild(work_area.render(), old_area);
// if sysop, check if CSD is already on the page and fill in custom rationale
if (isSysopMode && Twinkle.speedy.hasCSD) {
var customOption = $('input[name=csd][value=reason]')[0];
if (customOption) {
if (Twinkle.getPref('speedySelectionStyle') !== 'radioClick') {
// force listeners to re-init
customOption.click();
customOption.parentNode.appendChild(customOption.subgroup);
}
customOption.subgroup.querySelector('input').value = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
}
}
// enlarge G11 radio/checkbox and its label
if (document.querySelector('input[value="g11"]') && Twinkle.getPref('enlargeG11Input')) {
document.querySelector('input[value="g11"]').style = 'height: 2em; width: 2em; height: -moz-initial; width: -moz-initial; -moz-transform: scale(2); -o-transform: scale(2);';
document.querySelector('input[value="g11"]').labels[0].style = 'font-size: 1.5em; line-height: 1.5em;';
}
if (!isSysopMode && mw.config.get('wgPageContentModel') !== 'wikitext') {
$('[name=tag_options]').hide();
$('[name=work_area]').empty();
var message = [
conv({ hans: 'Twinkle不支持在页面内容模型为', hant: 'Twinkle不支援在頁面內容模型為' }),
mw.config.get('wgPageContentModel'),
conv({ hans: '的页面上挂上快速删除模板,请参见', hant: '的頁面上掛上快速刪除模板,請參見' }),
$('<a>').attr({ target: '_blank', href: mw.util.getUrl('WP:SPECIALSD') }).text(conv({ hans: '手动放置模板时的注意事项', hant: '手動放置模板時的注意事項' }))[0],
'。'
];
$('[name=work_area]').append(message);
Morebits.simpleWindow.setButtonsEnabled(false);
} else {
Morebits.simpleWindow.setButtonsEnabled(true);
}
};
Twinkle.speedy.callback.priorDeletionCount = function () {
var query = {
action: 'query',
format: 'json',
list: 'logevents',
letype: 'delete',
leaction: 'delete/delete', // Just pure page deletion, no redirect overwrites or revdel
letitle: mw.config.get('wgPageName'),
leprop: '', // We're just counting we don't actually care about the entries
lelimit: 5 // A little bit goes a long way
};
new Morebits.wiki.api(conv({ hans: '检查之前的删除', hant: '檢查之前的刪除' }), query, function (apiobj) {
var response = apiobj.getResponse();
var delCount = response.query.logevents.length;
if (delCount) {
var message = conv({ hans: '被删除', hant: '被刪除' });
if (response.continue) {
message += conv({ hans: '超过', hant: '超過' });
}
message += delCount + '次';
// 3+ seems problematic
if (delCount >= 3) {
$('#prior-deletion-count').css('color', 'red');
}
// Provide a link to page logs (CSD templates have one for sysops)
var link = Morebits.htmlNode('a', conv({ hans: '(日志)', hant: '(日誌)' }));
link.setAttribute('href', mw.util.getUrl('Special:Log', {page: mw.config.get('wgPageName')}));
link.setAttribute('target', '_blank');
$('#prior-deletion-count').text(message); // Space before log link
$('#prior-deletion-count').append(link);
}
}).post();
};
Twinkle.speedy.generateCsdList = function twinklespeedyGenerateCsdList(list, mode) {
// mode switches
var isSysopMode = Twinkle.speedy.mode.isSysop(mode);
var multiple = Twinkle.speedy.mode.isMultiple(mode);
var hasSubmitButton = Twinkle.speedy.mode.hasSubmitButton(mode);
var openSubgroupHandler = function(e) {
$(e.target.form).find('input').prop('disabled', true);
$(e.target.form).children().css('color', 'gray');
$(e.target).parent().css('color', 'black').find('input').prop('disabled', false);
$(e.target).parent().find('input:text')[0].focus();
e.stopPropagation();
};
var submitSubgroupHandler = function(e) {
var evaluateType = Twinkle.speedy.mode.isSysop(mode) ? 'evaluateSysop' : 'evaluateUser';
Twinkle.speedy.callback[evaluateType](e);
e.stopPropagation();
};
return $.map(list, function(critElement) {
var criterion = $.extend({}, critElement);
if (multiple) {
if (criterion.hideWhenMultiple) {
return null;
}
if (criterion.hideSubgroupWhenMultiple) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenSingle) {
return null;
}
if (criterion.hideSubgroupWhenSingle) {
criterion.subgroup = null;
}
}
if (isSysopMode) {
if (criterion.hideWhenSysop) {
return null;
}
if (criterion.hideSubgroupWhenSysop) {
criterion.subgroup = null;
}
} else {
if (criterion.hideWhenUser) {
return null;
}
if (criterion.hideSubgroupWhenUser) {
criterion.subgroup = null;
}
}
if (mw.config.get('wgIsRedirect') && criterion.hideWhenRedirect) {
return null;
}
if (criterion.showInNamespaces && criterion.showInNamespaces.indexOf(mw.config.get('wgNamespaceNumber')) < 0) {
return null;
} else if (criterion.hideInNamespaces && criterion.hideInNamespaces.indexOf(mw.config.get('wgNamespaceNumber')) > -1) {
return null;
}
if (criterion.subgroup && !hasSubmitButton) {
if ($.isArray(criterion.subgroup)) {
criterion.subgroup.push({
type: 'button',
name: 'submit',
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: submitSubgroupHandler
});
} else {
criterion.subgroup = [
criterion.subgroup,
{
type: 'button',
name: 'submit', // ends up being called "csd.submit" so this is OK
label: isSysopMode ? conv({ hans: '删除页面', hant: '刪除頁面' }) : conv({ hans: '标记页面', hant: '標記頁面' }),
event: submitSubgroupHandler
}
];
}
// FIXME: does this do anything?
criterion.event = openSubgroupHandler;
}
if (isSysopMode) {
var originalEvent = criterion.event;
criterion.event = function(e) {
if (multiple) {
return originalEvent(e);
}
var normalizedCriterion = Twinkle.speedy.normalizeHash[e.target.value];
$('[name=openusertalk]').prop('checked',
Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf(normalizedCriterion) !== -1
);
if (originalEvent) {
return originalEvent(e);
}
};
}
return criterion;
});
};
Twinkle.speedy.customRationale = [
{
label: conv({ hans: '自定义理由' + (Morebits.userIsSysop ? '(自定义删除理由)' : ''), hant: '自訂理由' + (Morebits.userIsSysop ? '(自訂刪除理由)' : '') }),
value: 'reason',
tooltip: conv({ hans: '该页至少应该符合一条快速删除的标准,并且您必须在理由中提到。这不是万能的删除理由。', hant: '該頁至少應該符合一條快速刪除的標準,並且您必須在理由中提到。這不是萬能的刪除理由。' }),
subgroup: {
name: 'reason_1',
type: 'input',
label: '理由:',
size: 60
}
// hideWhenMultiple: true
}
];
Twinkle.speedy.pseudoNSList = [
{
label: conv({ hans: 'O8. 在伪命名空间中创建的非重定向页', hant: 'O8. 在偽命名空間中建立的非重新導向頁面' }),
value: 'o8',
tooltip: conv({ hans: '伪命名空间仅能用于重定向。如可以移动到合适的名称,请将页面移动到合适的名称,否则请使用此款快速删除。若页面明显是一个条目,则不适用此款快速删除。', hant: '偽命名空間僅能用於重新導向。如可以移動到合適的名稱,請將頁面移動到合適的名稱,否則請使用此款快速刪除。若頁面明顯是一個條目,則不適用此款快速刪除。' })
}
];
Twinkle.speedy.fileList = [
{
label: conv({ hans: 'F1: 重复的文件(完全相同或缩小),而且不再被条目使用', hant: 'F1: 重複的檔案(完全相同或縮小),而且不再被條目使用' }),
value: 'f1',
subgroup: {
name: 'f1_filename',
type: 'input',
label: conv({ hans: '与此文件相同的文件名:', hant: '與此檔案相同的檔名:' }),
tooltip: conv({ hans: '可不含“File:”前缀。', hant: '可不含「File:」字首。' })
}
},
{
label: conv({ hans: 'F3: 来源不明的文件', hant: 'F3: 來源不明的檔案' }),
value: 'f3',
hideWhenUser: true
},
{
label: conv({ hans: 'F4: 未知著作权或著作权无法被查证的文件', hant: 'F4: 未知著作權或著作權無法被查證的檔案' }),
value: 'f4',
hideWhenUser: true
},
{
label: conv({ hans: 'F5: 被高清晰度或SVG文件取代的图片', hant: 'F5: 被高解析度或SVG檔案取代的圖片' }),
value: 'f5',
subgroup: {
name: 'f5_filename',
type: 'input',
label: conv({ hans: '新文件名:', hant: '新檔名:' }),
tooltip: conv({ hans: '可不含“File:”前缀。', hant: '可不含「File:」字首。' })
}
},
{
label: conv({ hans: 'F6: 没有被条目使用的非自由著作权文件', hant: 'F6: 沒有被條目使用的非自由著作權檔案' }),
value: 'f6',
hideWhenUser: true
},
{
label: conv({ hans: 'F7: 与维基共享资源文件重复的文件', hant: 'F7: 與維基共享資源檔案重複的檔案' }),
value: 'f7',
subgroup: {
name: 'f7_filename',
type: 'input',
label: conv({ hans: '维基共享资源上的文件名:', hant: '維基共享資源上的檔名:' }),
value: Morebits.pageNameNorm,
tooltip: conv({ hans: '如与本文件名相同则可留空,可不含“File:”前缀。', hant: '如與本檔名相同則可留空,可不含「File:」字首。' })
},
hideWhenMultiple: true
},
{
label: conv({ hans: 'F8: 明显侵权之文件', hant: 'F8: 明顯侵權之檔案' }),
value: 'f8',
hideWhenUser: true
},
{
label: conv({ hans: 'F9: 没有填写任何合理使用依据的非自由著作权文件', hant: 'F9: 沒有填寫任何合理使用依據的非自由著作權檔案' }),
value: 'f9',
hideWhenUser: true
},
{
label: conv({ hans: 'F10: 可被替代的非自由著作权文件', hant: 'F10: 可被替代的非自由著作權檔案' }),
value: 'f10',
hideWhenUser: true
}
];
Twinkle.speedy.articleList = [
{
label: conv({ hans: 'A1: 内容空泛(包括但不限于没有定义)。', hant: 'A1: 內容空泛(包括但不限於沒有定義)。' }),
value: 'a1',
tooltip: conv({ hans: '条目的内容笼统,或甚至根本没有提及条目主体,使条目不能用以区分其他事物。例如:“他是一个很有趣的人,他创建了工厂和庄园。并且,顺便提一下,他的妻子也很好。”<br>“内容空泛”与“没有实际内容”的分别在于:后者乃是与主题完全无关,或是不知所云;前者可以与主题有一定关系,但没有明确描述主题(包括但不限于没有对主题作基本定义);前者同时包含后者。', hant: '條目的內容籠統,或甚至根本沒有提及條目主體,使條目不能用以區分其他事物。例如:「他是一個很有趣的人,他建立了工廠和莊園。並且,順便提一下,他的妻子也很好。」<br>「內容空泛」與「沒有實際內容」的分別在於:後者乃是與主題完全無關,或是不知所云;前者可以與主題有一定關係,但沒有明確描述主題(包括但不限於沒有對主題作基本定義);前者同時包含後者。' })
},
{
label: conv({ hans: 'A2: 内容只包括外部链接、参见、图书参考、分类、模板、跨语言链接的条目', hant: 'A2: 內容只包括外部連結、參見、圖書參考、分類、模板、跨語言連結的條目' }),
value: 'a2',
tooltip: conv({ hans: '请注意:有些维基人创建条目时会分开多次保存,请避免删除有人正在编辑的页面。<br>带有{{inuse}}模板的不适用。', hant: '請注意:有些維基人建立條目時會分開多次儲存,請避免刪除有人正在編輯的頁面。<br>帶有{{inuse}}模板的不適用。' })
},
{
label: conv({ hans: 'A3: 复制自其他中文维基计划,或是与其他中文维基计划内容相同的文章。', hant: 'A3: 複製自其他中文維基計劃,或是與其他中文維基計劃內容相同的文章。' }),
value: 'a3',
subgroup: {
name: 'a3_pagename',
type: 'input',
label: conv({ hans: '现有条目名:', hant: '現有條目名:' }),
tooltip: conv({ hans: '请加上跨 wiki 前缀。不自动加上链接,若需要请自行加上[[]]。', hant: '請加上跨 wiki 字首。不自動加上連結,若需要請自行加上[[]]。' }),
size: 60
}
},
{
label: conv({ hans: 'A6: 复制自其他维基百科语言版本,且完全没有翻译。', hant: 'A6: 複製自其他維基百科語言版本,且完全沒有翻譯。' }),
value: 'a6',
tooltip: conv({ hans: '如果并不是复制于任何其他的维基百科语言版本,请换用{{notmandarin}}。<br>带有{{inuse}}和{{translating}}模板的不适用。', hant: '如果並不是複製於任何其他的維基百科語言版本,請換用{{notmandarin}}。<br>帶有{{inuse}}和{{translating}}模板的不適用。' }),
subgroup: {
name: 'a6_pagename',
type: 'input',
label: conv({ hans: '现有条目名:', hant: '現有條目名:' }),
tooltip: conv({ hans: '请加上跨 wiki 前缀。不自动加上链接,若需要请自行加上[[]]。', hant: '請加上跨 wiki 字首。不自動加上連結,若需要請自行加上[[]]。' }),
size: 60
}
}
];
Twinkle.speedy.categoryList = [
{
label: conv({ hans: 'O4: 空的分类(没有条目也没有子分类)。', hant: 'O4: 空的分類(沒有條目也沒有子分類)。' }),
value: 'o4',
tooltip: conv({ hans: '不适用于Category:不要删除的分类中的空分类。', hant: '不適用於Category:不要刪除的分類中的空分類。' })
}
];
Twinkle.speedy.draftList = [
{
label: conv({ hans: 'O7: 废弃草稿。', hant: 'O7: 廢棄草稿。' }),
value: 'o7',
tooltip: conv({ hans: '任何六个月内无编辑的草稿。', hant: '任何六個月內無編輯的草稿。' })
}
];
Twinkle.speedy.userList = [
{
label: conv({ hans: 'O1: 用户请求删除自己的用户页或其子页面。', hant: 'O1: 使用者請求刪除自己的使用者頁面或其子頁面。' }),
value: 'o1',
tooltip: conv({ hans: '除了自己的用户页,只要是移动而来的页面,皆须附有合理原因。', hant: '除了自己的使用者頁面,只要是移動而來的頁面,皆須附有合理原因。' })
}
];
Twinkle.speedy.usertalkList = [
{
label: conv({ hans: 'O3: 已超过一个月未有编辑动作的匿名(IP)用户的用户讨论页', hant: 'O3: 已超過一個月未有編輯動作的匿名(IP)使用者的使用者討論頁' }),
value: 'o3',
tooltip: conv({ hans: '避免给使用同一IP地址的用户带来混淆。<br>不适用于用户讨论页的存档页面。', hant: '避免給使用同一IP位址的使用者帶來混淆。<br>不適用於使用者討論頁的存檔頁面。' })
}
];
Twinkle.speedy.generalList = [
{
label: conv({ hans: 'G1: 没有实际内容的页面', hant: 'G1: 沒有實際內容的頁面' }),
value: 'g1',
tooltip: conv({ hans: '如“adfasddd”。参见Wikipedia:胡言乱语。但注意:图片也算是内容。', hant: '如「adfasddd」。參見Wikipedia:胡言亂語。但注意:圖片也算是內容。' }),
hideInNamespaces: [ 2, 3 ] // user, user talk
},
{
label: conv({ hans: 'G2: 测试页面', hant: 'G2: 測試頁面' }),
value: 'g2',
tooltip: conv({ hans: '例如:“这是一个测试。”', hant: '例如:「這是一個測試。」' }),
hideInNamespaces: [ 2, 3 ] // user, user talk
},
{
label: conv({ hans: 'G3: 纯粹破坏,包括但不限于明显的恶作剧、错误信息、人身攻击等', hant: 'G3: 純粹破壞,包括但不限於明顯的惡作劇、錯誤資訊、人身攻擊等' }),
value: 'g3',
tooltip: conv({ hans: '包括明显的错误信息、明显的恶作剧、信息明显错误的图片,以及清理移动破坏时留下的重定向。', hant: '包括明顯的錯誤資訊、明顯的惡作劇、資訊明顯錯誤的圖片,以及清理移動破壞時留下的重新導向。' })
},
{
label: conv({ hans: 'G5: 曾经根据页面存废讨论<s>、侵权审核</s>或文件存废讨论结果删除后又重新创建的内容,而有关内容与已删除版本相同或非常相似,无论标题是否相同', hant: 'G5: 曾經根據頁面存廢討論<s>、侵權審核</s>或檔案存廢討論結果刪除後又重新建立的內容,而有關內容與已刪除版本相同或非常相似,無論標題是否相同' }),
value: 'g5',
tooltip: conv({ hans: '该内容之前必须是经存废讨论删除。<br>如该内容之前属于快速删除,请以相同理由重新提送快速删除。<br>该内容如与被删除的版本明显不同,而提删者认为需要删除,请交到存废讨论,如果提删者对此不肯定,请先联系上次执行删除的管理人员。<br>不适用于根据存废复核结果被恢复的内容。在某些情况下,重新创建的条目有机会发展,那么不应提交快速删除,而应该提交存废复核或存废讨论重新评核。', hant: '該內容之前必須是經存廢討論刪除。<br>如該內容之前屬於快速刪除,請以相同理由重新提送快速刪除。<br>該內容如與被刪除的版本明顯不同,而提刪者認為需要刪除,請交到存廢討論,如果提刪者對此不肯定,請先聯絡上次執行刪除的管理人員。<br>不適用於根據存廢覆核結果被恢復的內容。在某些情況下,重新建立的條目有機會發展,那麼不應提交快速刪除,而應該提交存廢覆核或存廢討論重新評核。' }),
subgroup: [
{
name: 'g5_1',
type: 'input',
label: conv({ hans: '删除讨论位置:', hant: '刪除討論位置:' }),
size: 60
},
{
type: 'div',
label: conv({ hans: '对于侵权页面,请使用Twinkle的“侵权”功能。', hant: '對於侵權頁面,請使用Twinkle的「侵權」功能。' })
}
],
hideSubgroupWhenMultiple: true
},
{
label: conv({ hans: 'G8: 因技术原因删除页面', hant: 'G8: 因技術原因刪除頁面' }),
value: 'g8',
tooltip: conv({ hans: '包括解封用户后删除用户页、因用户夺取而删除、删除无用的MediaWiki页面、因移动请求而删除页面、以改写删除重定向。', hant: '包括解封使用者後刪除使用者頁面、因使用者奪取而刪除、刪除無用的MediaWiki頁面、因移動請求而刪除頁面、以覆寫刪除重新導向。' }),
hideWhenUser: true
},
{
label: conv({ hans: 'G10: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: 'G10: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' }),
value: 'g10',
tooltip: conv({ hans: '提请须出于善意,并附有合理原因。', hant: '提請須出於善意,並附有合理原因。' }),
subgroup: {
name: 'g10_rationale',
type: 'input',
label: conv({ hans: '可选的解释:', hant: '可選的解釋:' }),
tooltip: conv({ hans: '比如作者在哪里请求了删除。', hant: '比如作者在哪裡請求了刪除。' }),
size: 60
},
hideSubgroupWhenSysop: true
},
{
label: conv({ hans: 'G11: 明显的广告宣传页面,或只有相关人物或团体的联系方法的页面', hant: 'G11: 明顯的廣告宣傳頁面,或只有相關人物或團體的聯絡方法的頁面' }),
value: 'g11',
tooltip: conv({ hans: '页面只收宣传之用,并须完全重写才能贴合百科全书要求。须注意,仅仅以某公司或产品为主题的条目,并不直接导致其自然满足此速删标准。<br>即便该页面具有宣传情况,除非您可以非常确定该页面创建仅为广告宣传而建,否则应以关注度提报或提删替代。', hant: '頁面只收宣傳之用,並須完全重寫才能貼合百科全書要求。須注意,僅僅以某公司或產品為主題的條目,並不直接導致其自然滿足此速刪標準。<br>即便該頁面具有宣傳情況,除非您可以非常確定該頁面建立僅為廣告宣傳而建,否則應以關注度提報或提刪替代。' })
},
{
label: conv({ hans: 'G12: 未列明可靠来源且语调负面的生者传记', hant: 'G12: 未列明可靠來源且語調負面的生者傳記' }),
value: 'g12',
tooltip: conv({ hans: '“列明”指至少一个列出的来源可直接支撑条目中的任何信息,并与其中的断言相匹配。<br>如有用户对条目中列出的来源是否属于可靠来源提出合理异议,则应交由存废讨论处理。<br>注意是未列明可靠来源且语调负面,须2项均符合方适用此项。', hant: '「列明」指至少一個列出的來源可直接支撐條目中的任何資訊,並與其中的斷言相匹配。<br>如有使用者對條目中列出的來源是否屬於可靠來源提出合理異議,則應交由存廢討論處理。<br>注意是未列明可靠來源且語調負面,須2項均符合方適用此項。' })
},
{
label: conv({ hans: 'G13: 翻译拙劣', hant: 'G13: 翻譯拙劣' }),
value: 'g13',
tooltip: conv({ hans: '不适用于所有的讨论命名空间、草稿命名空间和用户命名空间。', hant: '不適用於所有的討論命名空間、草稿命名空間和使用者命名空間。' }),
hideInNamespaces: [ 1, 2, 3, 5, 7, 9, 11, 13, 15, 101, 118, 119, 829 ] // all talk, user, draft
},
{
label: conv({ hans: 'G14: 超过两周没有进行任何翻译的非现代标准汉语页面', hant: 'G14: 超過兩週沒有進行任何翻譯的非現代標準漢語頁面' }),
value: 'g14',
tooltip: conv({ hans: '包括所有未翻译的外语、汉语方言以及文言文。<br>此项仅适用于条目、项目、维基专题、使用说明和主题命名空间。', hant: '包括所有未翻譯的外語、漢語方言以及文言文。<br>此項僅適用於條目、計畫、維基專題、使用說明和主題命名空間。' }),
hideWhenUser: true,
showInNamespaces: [ 0, 4, 12, 100, 102 ] // main, wikipedia, help, portal, wikiproject
},
{
label: conv({ hans: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等', hant: 'G15: 孤立頁面,比如沒有主頁面的討論頁、指向空頁面的重新導向等' }),
value: 'g15',
tooltip: conv({ hans: '包括以下几种类型:<br>1. 没有对应文件的文件页面;<br>2. 没有对应母页面的子页面,用户页子页面除外;<br>3. 指向不存在页面的重定向;<br>4. 没有对应内容页面的讨论页,讨论页存档和用户讨论页除外;<br>5. 不存在注册用户的用户页及用户页子页面,localhost对应IP用户的用户页和随用户更名产生的用户页重定向除外。<br>请在删除时注意有无将内容移至他处的必要。<br>不包括在主页面挂有{{CSD Placeholder}}模板的讨论页。', hant: '包括以下幾種類型:<br>1. 沒有對應檔案的檔案頁面;<br>2. 沒有對應母頁面的子頁面,使用者頁面子頁面除外;<br>3. 指向不存在頁面的重新導向;<br>4. 沒有對應內容頁面的討論頁,討論頁存檔和使用者討論頁除外;<br>5. 不存在註冊使用者的使用者頁面及使用者頁面子頁面,localhost對應IP使用者的使用者頁面和隨使用者更名產生的使用者頁面重新導向除外。<br>請在刪除時注意有無將內容移至他處的必要。<br>不包括在主頁面掛有{{CSD Placeholder}}模板的討論頁。' })
},
{
label: conv({ hans: 'G17: 位于不恰当的命名空间的消歧义页面', hant: 'G17: 位於不恰當的命名空間的消歧義頁面' }),
value: 'g17',
tooltip: conv({ hans: '在提请快速删除前,请务必先检查并清理相关消歧义页面的链入。<br>此项不论页面是否引用消歧义模板或消歧义消息模板均适用,惟对消歧义模板及消歧义消息模板本身不适用。', hant: '在提請快速刪除前,請務必先檢查並清理相關消歧義頁面的連入。<br>此項不論頁面是否引用消歧義模板或消歧義訊息模板均適用,惟對消歧義模板及消歧義訊息模板本身不適用。' }),
hideInNamespaces: [ 0, 1, 2, 3, 4, 5, 118, 119 ] // main, user, project, draft and theirs talks
},
{
label: conv({ hans: 'G18: 条目或草稿创建时,内容即与其他现有条目或草稿或其历史版本的内容完全相同或非常相似,且名称不适合作为其他条目之重定向', hant: 'G18: 條目或草稿建立時,內容即與其他現有條目或草稿或其歷史版本的內容完全相同或非常相似,且名稱不適合作為其他條目之重新導向' }),
value: 'g18',
tooltip: conv({ hans: '条目或草稿创建时,首个版本的内容与当时其他现存条目或草稿或其历史版本的全部或部分内容完全相同或非常相似,且其名称不适合改为重定向,就可以提送快速删除。<br>如果名称可以作为重定向,就应直接改为重定向,不要提送快速删除。<br>如果是多个条目或草稿合并产生的新条目或草稿,不适用。<br>如果是从主条目或草稿拆分产生的条目或草稿,不适用;如有疑虑,应提送存废讨论处理。', hant: '條目或草稿建立時,首個版本的內容與當時其他現存條目或草稿或其歷史版本的全部或部分內容完全相同或非常相似,且其名稱不適合改為重新導向,就可以提送快速刪除。<br>如果名稱可以作為重新導向,就應直接改為重新導向,不要提送快速刪除。<br>如果是多個條目或草稿合併產生的新條目或草稿,不適用。<br>如果是從主條目或草稿拆分產生的條目或草稿,不適用;如有疑慮,應提送存廢討論處理。' }),
subgroup: {
name: 'g18_pagename',
type: 'input',
label: conv({ hans: '现有页面名:', hant: '現有頁面名:' }),
size: 60
},
showInNamespaces: [ 0, 2, 118 ] // main, user, draft
}
];
Twinkle.speedy.redirectList = [
{
label: conv({ hans: 'R2: 跨命名空间重定向。', hant: 'R2: 跨命名空間重新導向。' }),
value: 'r2',
tooltip: conv({ hans: '适用于条目命名空间和草稿命名空间。<br>社群同意设立的伪命名空间不适用。<br>草稿重定向速删前,请确保草稿已经完成其作用,且其历史已移动到相应的正式页面。', hant: '適用於條目命名空間和草稿命名空間。<br>社群同意設立的偽命名空間不適用。<br>草稿重新導向速刪前,請確保草稿已經完成其作用,且其歷史已移動到相應的正式頁面。' }),
showInNamespaces: [ 0, 118 ] // main, draft
},
{
label: conv({ hans: 'R3: 格式错误,或明显笔误的重定向。', hant: 'R3: 格式錯誤,或明顯筆誤的重新導向。' }),
value: 'r3',
tooltip: conv({ hans: '非一眼能看出的拼写错误和翻译或标题用字的争议应交由存废讨论处理。<br>将常见的拼写错误名称重定向至正确名称页面,可使百科用户纵使在查找文章时拼写错误,也能够找到寻求的文章。可参阅WP:重定向#何时用重定向?。<br>如重定向名称与导向目标名称(或其相关名称)仅存在合理的大小写差异及/或重定向名称为导向目标名称(或其相关名称)的ASCII字母表述的形式(例如Kurt Godel重定向至Kurt Gödel),不视为存在任何拼写错误。如有对相关大小写差异是否合理的争议,应交由存废讨论处理。<br>因类推简化字未收录至《通用规范汉字表》导致的繁简混杂情形,或系统无法自动进行繁简处理的情形,则不适用。', hant: '非一眼能看出的拼寫錯誤和翻譯或標題用字的爭議應交由存廢討論處理。<br>將常見的拼寫錯誤名稱重新導向至正確名稱頁面,可使百科使用者縱使在尋找文章時拼寫錯誤,也能夠找到尋求的文章。可參閱WP:重新導向#何時用重新導向?。<br>如重新導向名稱與導向目標名稱(或其相關名稱)僅存在合理的大小寫差異及/或重新導向名稱為導向目標名稱(或其相關名稱)的ASCII字母表述的形式(例如Kurt Godel重新導向至Kurt Gödel),不視為存在任何拼寫錯誤。如有對相關大小寫差異是否合理的爭議,應交由存廢討論處理。<br>因類推簡化字未收錄至《通用規範漢字表》導致的繁簡混雜情形,或系統無法自動進行繁簡處理的情形,則不適用。' }),
subgroup: {
name: 'r3_type',
type: 'select',
label: conv({ hans: '适用类型:', hant: '適用類別:' }),
list: [
{ label: conv({ hans: '请选择', hant: '請選擇' }), value: '' },
{ label: conv({ hans: '标题繁简混用', hant: '標題繁簡混用' }), value: '标题繁简混用。' },
{ label: conv({ hans: '消歧义使用的括号或空格错误', hant: '消歧義使用的括號或空格錯誤' }), value: '消歧义使用的括号或空格错误。' },
{ label: conv({ hans: '间隔号使用错误', hant: '間隔號使用錯誤' }), value: '间隔号使用错误。' },
{ label: conv({ hans: '标题中使用非常见的错别字', hant: '標題中使用非常見的錯別字' }), value: '标题中使用非常见的错别字。' }
]
},
hideSubgroupWhenSysop: true
},
{
label: conv({ hans: 'R5: 指向本身或循环的重定向。', hant: 'R5: 指向本身或循環的重新導向。' }),
value: 'r5',
tooltip: '如A→B→C→……→A。'
},
{
label: conv({ hans: 'R6: 移动文件而产生的重定向,且页面标题不符合文件名指引。', hant: 'R6: 移動檔案而產生的重新導向,且頁面標題不符合檔案名稱指引。' }),
value: 'r6',
showInNamespaces: [ 6 ] // file
},
{
label: conv({ hans: 'R7: 明显与导向目标所涵盖的主题无关或比导向目标所涵盖的主题更广泛的重定向。', hant: 'R7: 明顯與導向目標所涵蓋的主題無關或比導向目標所涵蓋的主題更廣泛的重新導向。' }),
value: 'r7',
tooltip: conv({ hans: '条目完全未提及重定向的名称,或重定向名称比条目主题更广泛,但条目不含有重定向名称的有效介绍。同时,重定向名称并不是条目的别名或错误拼写。有争议的情况下,应提出存废讨论。<br>如果原重定向标题可改成消歧义页(或重定向至其他消歧义页),则不适用。<br>挂有{{关注度重定向}}或{{合并重定向}}模板的页面不适用,请改为提出存废讨论。<br>如有用户对标题用字存在未解决的争议,则应交由存废讨论处理。', hant: '條目完全未提及重新導向的名稱,或重新導向名稱比條目主題更廣泛,但條目不含有重新導向名稱的有效介紹。同時,重新導向名稱並不是條目的別名或錯誤拼寫。有爭議的情況下,應提出存廢討論。<br>如果原重新導向標題可改成消歧義頁(或重新導向至其他消歧義頁),則不適用。<br>掛有{{關注度重新導向}}或{{合併重新導向}}模板的頁面不適用,請改為提出存廢討論。<br>如有使用者對標題用字存在未解決的爭議,則應交由存廢討論處理。' })
},
{
label: conv({ hans: 'R8: 带有“(消歧义)”字样,且无链入的重定向。', hant: 'R8: 帶有「(消歧義)」字樣,且無連入的重新導向。' }),
value: 'r8',
tooltip: conv({ hans: '若重定向页与导向目标页同样带有“(消歧义)”字样,且两者的标题仅存在繁简/地区词差异,则不适用。<br在提请快速删除前,请务必先检查并清理(如适用)相关重定向的链入。<br>如有用户对应否使用消歧义及消歧义的方式存在未解决的争议,则应交由存废讨论处理。', hant: '若重新導向頁面與導向目標頁同樣帶有「(消歧義)」字樣,且兩者的標題僅存在繁簡/地區詞差異,則不適用。<br在提請快速刪除前,請務必先檢查並清理(如適用)相關重新導向的連入。<br>如有使用者對應否使用消歧義及消歧義的方式存在未解決的爭議,則應交由存廢討論處理。' })
}
];
Twinkle.speedy.normalizeHash = {
'reason': 'db',
'multiple': 'multiple',
'multiple-finish': 'multiple-finish',
'g1': 'g1',
'g2': 'g2',
'g3': 'g3',
'g5': 'g5',
'g8': 'g8',
'g10': 'g10',
'g11': 'g11',
'g12': 'g12',
'g13': 'g13',
'g14': 'g14',
'g15': 'g15',
'g16': 'g16',
'g17': 'g17',
'g18': 'g18',
'a1': 'a1',
'a2': 'a2',
'a3': 'a3',
'a6': 'a6',
'r2': 'r2',
'r3': 'r3',
'r5': 'r5',
'r6': 'r6',
'r7': 'r7',
'r8': 'r8',
'f1': 'f1',
'f3': 'f3',
'f4': 'f4',
'f5': 'f5',
'f6': 'f6',
'f7': 'f7',
'o1': 'o1',
'o3': 'o3',
'o4': 'o4',
'o7': 'o7',
'o8': 'o8'
};
Twinkle.speedy.callbacks = {
getTemplateCodeAndParams: function(params) {
var code, parameters, i;
if (params.normalizeds.length > 1) {
code = '{{delete';
params.utparams = {};
$.each(params.normalizeds, function(index, norm) {
if (norm !== 'db') {
code += '|' + norm.toUpperCase();
}
parameters = params.templateParams[index] || [];
for (var i in parameters) {
if (typeof parameters[i] === 'string') {
code += '|' + parameters[i];
}
}
$.extend(params.utparams, Twinkle.speedy.getUserTalkParameters(norm, parameters));
});
code += '}}';
} else {
parameters = params.templateParams[0] || [];
code = '{{delete';
if (params.values[0] !== 'reason') {
code += '|' + params.values[0];
}
for (i in parameters) {
if (typeof parameters[i] === 'string') {
code += '|' + parameters[i];
}
}
code += '}}';
params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalizeds[0], parameters);
}
return [code, params.utparams];
},
parseWikitext: function(title, wikitext, callback) {
var query = {
action: 'parse',
prop: 'text',
pst: 'true',
text: wikitext,
contentmodel: 'wikitext',
title: title
};
var statusIndicator = new Morebits.status(conv({ hans: '构造删除理由', hant: '構造刪除理由' }));
var api = new Morebits.wiki.api(conv({ hans: '解析删除模板', hant: '解析刪除模板' }), query, function (apiObj) {
var reason = decodeURIComponent($(apiObj.getXML().querySelector('text').childNodes[0].nodeValue).find('#delete-reason').text().replace(/\+/g, ' '));
if (!reason) {
statusIndicator.warn(conv({ hans: '未能从删除模板生成删除理由', hant: '未能從刪除模板生成刪除理由' }));
} else {
statusIndicator.info('完成');
}
callback(reason);
}, statusIndicator);
api.post();
},
sysop: {
main: function(params) {
var reason;
if (!params.normalizeds.length && params.normalizeds[0] === 'db') {
reason = prompt(conv({ hans: '输入删除理由:', hant: '輸入刪除理由:' }), '');
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
} else {
var code = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params)[0];
Twinkle.speedy.callbacks.parseWikitext(mw.config.get('wgPageName'), code, function(reason) {
if (params.promptForSummary) {
reason = prompt(conv({ hans: '输入删除理由,或单击确定以接受自动生成的:', hant: '輸入刪除理由,或點擊確定以接受自動生成的:' }), reason);
}
Twinkle.speedy.callbacks.sysop.deletePage(reason, params);
});
}
},
deletePage: function(reason, params) {
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '删除页面', hant: '刪除頁面' }));
if (reason === null) {
return Morebits.status.error(conv({ hans: '询问理由', hant: '詢問理由' }), conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
} else if (!reason || !reason.replace(/^\s*/, '').replace(/\s*$/, '')) {
return Morebits.status.error(conv({ hans: '询问理由', hant: '詢問理由' }), conv({ hans: '你不给我理由…我就…不管了…', hant: '你不給我理由…我就…不管了…' }));
}
var deleteMain = function() {
thispage.setEditSummary(reason);
thispage.setChangeTags(Twinkle.changeTags);
thispage.setWatchlist(params.watch);
thispage.deletePage(function() {
thispage.getStatusElement().info('完成');
Twinkle.speedy.callbacks.sysop.deleteTalk(params);
});
};
// look up initial contributor. If prompting user for deletion reason, just display a link.
// Otherwise open the talk page directly
if (params.openUserTalk) {
thispage.setCallbackParameters(params);
thispage.lookupCreation(function() {
Twinkle.speedy.callbacks.sysop.openUserTalkPage(thispage);
deleteMain();
});
} else {
deleteMain();
}
},
deleteTalk: function(params) {
// delete talk page
if (params.deleteTalkPage &&
params.normalized !== 'f7' &&
params.normalized !== 'o1' &&
!document.getElementById('ca-talk').classList.contains('new')) {
var talkpage = new Morebits.wiki.page(mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber') + 1] + ':' + mw.config.get('wgTitle'), conv({ hans: '删除讨论页', hant: '刪除討論頁' }));
talkpage.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 已删除页面“' + Morebits.pageNameNorm + '”的讨论页');
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.deletePage();
// this is ugly, but because of the architecture of wiki.api, it is needed
// (otherwise success/failure messages for the previous action would be suppressed)
window.setTimeout(function() {
Twinkle.speedy.callbacks.sysop.deleteRedirects(params);
}, 1800);
} else {
Twinkle.speedy.callbacks.sysop.deleteRedirects(params);
}
},
deleteRedirects: function(params) {
// delete redirects
if (params.deleteRedirects) {
var query = {
action: 'query',
titles: mw.config.get('wgPageName'),
prop: 'redirects',
rdlimit: 5000 // 500 is max for normal users, 5000 for bots and sysops
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '获取重定向列表…', hant: '取得重新導向列表…' }), query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
new Morebits.status(conv({ hans: '删除重定向', hant: '刪除重新導向' })));
wikipedia_api.params = params;
wikipedia_api.post();
}
// prompt for protect on G11
var $link, $bigtext;
if (params.normalized === 'g11') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里施行保护', hant: '點擊這裡施行保護' }),
css: { fontSize: '130%', fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
mw.config.set('wgArticleId', 0);
Twinkle.protect.callback();
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '白纸保护该页', hant: '白紙保護該頁' }),
css: { fontSize: '130%', fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
}
// promote Unlink tool
if (mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f7') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里前往取消链入工具', hant: '點擊這裡前往取消連入工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback(conv({ hans: '取消对已删除文件 ', hant: '取消對已刪除檔案 ' }) + Morebits.pageNameNorm + ' 的使用');
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '取消对已删除文件的使用', hant: '取消對已刪除檔案的使用' }),
css: { fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else if (params.normalized !== 'f7') {
$link = $('<a/>', {
href: '#',
text: conv({ hans: '单击这里前往取消链入工具', hant: '點擊這裡前往取消連入工具' }),
css: { fontWeight: 'bold' },
click: function() {
Morebits.wiki.actionCompleted.redirect = null;
Twinkle.speedy.dialog.close();
Twinkle.unlink.callback(conv({ hans: '取消对已删除页面 ', hant: '取消對已刪除頁面 ' }) + Morebits.pageNameNorm + conv({ hans: ' 的链接', hant: ' 的連結' }));
}
});
$bigtext = $('<span/>', {
text: conv({ hans: '取消对已删除页面的链接', hant: '取消對已刪除頁面的連結' }),
css: { fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
}
$link = $('<a>', {
href: mw.util.getUrl('Special:RandomInCategory/快速删除候选'),
text: conv({ hans: '单击前往下一个快速删除候选', hant: '點擊前往下一個快速刪除候選' })
});
Morebits.status.info('工具', $link[0]);
},
openUserTalkPage: function(pageobj) {
pageobj.getStatusElement().unlink(); // don't need it anymore
var user = pageobj.getCreator();
var params = pageobj.getCallbackParameters();
var query = {
title: 'User talk:' + user,
action: 'edit',
preview: 'yes',
vanarticle: Morebits.pageNameNorm
};
if (params.normalized === 'db' || Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(params.normalized) !== -1) {
// provide a link to the user talk page
var $link, $bigtext;
$link = $('<a/>', {
href: mw.util.wikiScript('index') + '?' + $.param(query),
text: conv({ hans: '点此打开User talk:', hant: '點此打開User talk:' }) + user,
target: '_blank',
css: { fontSize: '130%', fontWeight: 'bold' }
});
$bigtext = $('<span/>', {
text: conv({ hans: '通知页面创建者', hant: '通知頁面建立者' }),
css: { fontSize: '130%', fontWeight: 'bold' }
});
Morebits.status.info($bigtext[0], $link[0]);
} else {
// open the initial contributor's talk page
var statusIndicator = new Morebits.status(conv({ hans: '打开用户', hant: '打開使用者' }) + user + conv({ hans: '的讨论页编辑窗口', hant: '的討論頁編輯視窗' }), conv({ hans: '打开中…', hant: '打開中…' }));
switch (Twinkle.getPref('userTalkPageMode')) {
case 'tab':
window.open(mw.util.wikiScript('index') + '?' + $.param(query), '_blank');
break;
case 'blank':
window.open(mw.util.wikiScript('index') + '?' + $.param(query), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
case 'window':
/* falls through */
default:
window.open(mw.util.wikiScript('index') + '?' + $.param(query),
window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
}
statusIndicator.info('完成');
}
},
deleteRedirectsMain: function(apiobj) {
var xmlDoc = apiobj.getXML();
var $snapshot = $(xmlDoc).find('redirects rd');
var total = $snapshot.length;
var statusIndicator = apiobj.statelem;
if (!total) {
statusIndicator.info(conv({ hans: '未发现重定向', hant: '未發現重新導向' }));
return;
}
statusIndicator.status('0%');
var current = 0;
var onsuccess = function(apiobjInner) {
var now = parseInt(100 * ++current / total, 10) + '%';
statusIndicator.update(now);
apiobjInner.statelem.unlink();
if (current >= total) {
statusIndicator.info(now + '(完成)');
Morebits.wiki.removeCheckpoint();
}
};
Morebits.wiki.addCheckpoint();
$snapshot.each(function(key, value) {
var title = $(value).attr('title');
var page = new Morebits.wiki.page(title, conv({ hans: '删除重定向 "', hant: '刪除重新導向 "' }) + title + '"');
page.setEditSummary('[[WP:CSD#G15|G15]]: 孤立页面: 重定向到已删除页面“' + Morebits.pageNameNorm + '”');
page.setChangeTags(Twinkle.changeTags);
page.deletePage(onsuccess);
});
}
},
user: {
main: function(pageobj) {
var statelem = pageobj.getStatusElement();
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
statelem.status(conv({ hans: '检查页面已有标记…', hant: '檢查頁面已有標記…' }));
// check for existing deletion tags
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|deletebecause|speedy|csd|速刪|速删|快删|快刪)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && !confirm(conv({ hans: '在页面上找到快速删除模板,要移除并加入新的吗?', hant: '在頁面上找到快速刪除模板,要移除並加入新的嗎?' }))) {
statelem.error(conv({ hans: '快速删除模板已被置于页面中。', hant: '快速刪除模板已被置於頁面中。' }));
return;
}
text = textNoSd;
var copyvio = /(?:\{\{\s*(copyvio|侵权|侵權)[^{}]*?\}\})/i.exec(text);
if (copyvio && !confirm(conv({ hans: '著作权验证模板已被置于页面中,您是否仍想加入一个快速删除模板?', hant: '著作權驗證模板已被置於頁面中,您是否仍想加入一個快速刪除模板?' }))) {
statelem.error(conv({ hans: '页面中已有著作权验证模板。', hant: '頁面中已有著作權驗證模板。' }));
return;
}
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想加入一个快速删除模板?', hant: '}}已被置於頁面中,您是否仍想加入一個快速刪除模板?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// returns => [<string> wikitext, <object> utparams]
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
code = buildData[0];
params.utparams = buildData[1];
var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
// patrol the page, if reached from Special:NewPages
if (Twinkle.getPref('markSpeedyPagesAsPatrolled')) {
thispage.patrol();
}
// Wrap SD template in noinclude tags if we are in template space.
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = '<noinclude>' + code + '</noinclude>';
}
// Remove tags that become superfluous with this action
text = text.replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
if (mw.config.get('wgNamespaceNumber') === 6) {
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
if (params.requestsalt) {
code = '{{salt}}\n' + code;
}
// Generate edit summary for edit
var editsummary;
if (params.normalizeds.length > 1) {
editsummary = conv({ hans: '请求快速删除(', hant: '請求快速刪除(' });
$.each(params.normalizeds, function(index, norm) {
if (norm !== 'db') {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']]、';
}
});
editsummary = editsummary.substr(0, editsummary.length - 1); // remove trailing comma
editsummary += ')';
} else if (params.normalizeds[0] === 'db') {
editsummary = conv({ hans: '请求[[WP:CSD|快速删除]]:', hant: '請求[[WP:CSD|快速刪除]]:' }) + params.templateParams[0]['1'];
} else {
editsummary = conv({ hans: '请求快速删除', hant: '請求快速刪除' }) + '([[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']])';
}
// Blank attack pages
if (params.blank) {
text = code;
} else {
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(code + '\n', Twinkle.hatnoteRegex).getText();
}
pageobj.setPageText(text);
pageobj.setEditSummary(editsummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(params.watch);
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
},
tagComplete: function(pageobj) {
var params = pageobj.getCallbackParameters();
// Notification to first contributor
if (params.usertalk) {
var callback = function(pageobj) {
var initialContrib = pageobj.getCreator();
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
Morebits.status.warn('您(' + initialContrib + conv({ hans: ')创建了该页,跳过通知', hant: ')建立了該頁,跳過通知' }));
initialContrib = null;
// don't notify users when their user talk page is nominated
} else if (initialContrib === mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') === 3) {
Morebits.status.warn(conv({ hans: '通知页面创建者:用户创建了自己的讨论页', hant: '通知頁面建立者:使用者建立了自己的討論頁' }));
initialContrib = null;
// quick hack to prevent excessive unwanted notifications. Should actually be configurable on recipient page...
} else if (initialContrib === 'A2093064-bot' && params.normalizeds[0] === 'g15') {
Morebits.status.warn(conv({ hans: '通知页面创建者:由机器人创建,跳过通知', hant: '通知頁面建立者:由機器人建立,跳過通知' }));
initialContrib = null;
} else {
var talkPageName = 'User talk:' + initialContrib;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
flowpage.setTopic('[[:' + Morebits.pageNameNorm + ']]的快速删除通知');
flowpage.setContent('{{subst:db-notice|target=' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.newTopic();
}, function() {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')'),
notifytext;
notifytext = '\n{{subst:db-notice|target=' + Morebits.pageNameNorm;
notifytext += (params.welcomeuser ? '' : '|nowelcome=yes') + '}}--~~~~';
var editsummary = '通知:';
if (params.normalizeds.indexOf('g12') === -1) { // no article name in summary for G10 deletions
editsummary += '页面[[' + Morebits.pageNameNorm + ']]';
} else {
editsummary += '一攻击性页面';
}
editsummary += '快速删除提名';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(editsummary);
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
};
var thispage = new Morebits.wiki.page(Morebits.pageNameNorm);
thispage.lookupCreation(callback);
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
},
// note: this code is also invoked from twinkleimage
// the params used are:
// for CSD: params.values, params.normalizeds (note: normalizeds is an array)
// for DI: params.fromDI = true, params.templatename, params.normalized (note: normalized is a string)
addToLog: function(params, initialContrib) {
var usl = new Morebits.userspaceLogger(Twinkle.getPref('speedyLogPageName'));
usl.initialText =
'这是该用户使用[[WP:TW|Twinkle]]的速删模块做出的[[WP:CSD|快速删除]]提名列表。\n\n' +
'如果您不再想保留此日志,请在[[' + Twinkle.getPref('configPage') + '|参数设置]]中关掉,并' +
'使用[[WP:CSD#O1|CSD O1]]提交快速删除。' +
(Morebits.userIsSysop ? '\n\n此日志并不记录用Twinkle直接执行的删除。' : '');
var appendText = '# [[:' + Morebits.pageNameNorm + ']]:';
if (params.fromDI) {
if (params.normalized === 'f3 f4') {
appendText += '图版[[WP:CSD#F3|CSD F3]]+[[WP:CSD#F4|CSD F4]]({{tl|no source no license/auto}})';
} else {
appendText += '图版[[WP:CSD#' + params.normalized.toUpperCase() + '|CSD ' + params.normalized.toUpperCase() + ']]({{tl|' + params.templatename + '}})';
}
} else {
if (params.normalizeds.length > 1) {
appendText += '多个理由(';
$.each(params.normalizeds, function(index, norm) {
appendText += '[[WP:CSD#' + norm.toUpperCase() + '|' + norm.toUpperCase() + ']]、';
});
appendText = appendText.substr(0, appendText.length - 1); // remove trailing comma
appendText += ')';
} else if (params.normalizeds[0] === 'db') {
appendText += '自定义理由';
} else {
appendText += '[[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']]';
}
}
if (params.requestsalt) {
appendText += conv({ hans: ';请求白纸保护', hant: ';請求白紙保護' });
}
if (initialContrib) {
appendText += ';通知{{user|' + initialContrib + '}}';
}
appendText += ' ~~~~~\n';
usl.changeTags = Twinkle.changeTags;
usl.log(appendText, conv({ hans: '记录对[[', hant: '記錄對[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的快速删除提名', hant: ']]的快速刪除提名' }));
}
}
};
// validate subgroups in the form passed into the speedy deletion tag
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(form, values) {
var parameters = [];
$.each(values, function(index, value) {
var currentParams = [];
var redimage;
switch (value) {
case 'reason':
if (form['csd.reason_1']) {
var dbrationale = form['csd.reason_1'].value;
if (!dbrationale || !dbrationale.trim()) {
alert(conv({ hans: '自定义理由:请指定理由。', hant: '自訂理由:請指定理由。' }));
parameters = null;
return false;
}
currentParams['1'] = dbrationale;
}
break;
case 'a3':
if (form['csd.a3_pagename'] && form['csd.a3_pagename'].value) {
currentParams.pagename = form['csd.a3_pagename'].value;
}
break;
case 'a6':
if (form['csd.a6_pagename'] && form['csd.a6_pagename'].value) {
currentParams.pagename = form['csd.a6_pagename'].value;
}
break;
case 'g5':
if (form['csd.g5_1']) {
var deldisc = form['csd.g5_1'].value;
if (deldisc) {
if (!/^(Wikipedia|WP|维基百科|維基百科):/i.test(deldisc)) {
alert(conv({ hans: 'CSD G5:您提供的讨论页名必须以“Wikipedia:”开头。', hant: 'CSD G5:您提供的討論頁名必須以「Wikipedia:」開頭。' }));
parameters = null;
return false;
}
currentParams['1'] = deldisc;
}
}
break;
case 'g10':
if (form['csd.g10_rationale'] && form['csd.g10_rationale'].value) {
currentParams.rationale = form['csd.g10_rationale'].value;
}
break;
case 'g16':
if (form['csd.g16_pagename']) {
var pagename = form['csd.g16_pagename'].value;
if (!pagename || !pagename.trim()) {
alert(conv({ hans: 'CSD G16:请提供页面名称。', hant: 'CSD G16:請提供頁面名稱。' }));
parameters = null;
return false;
}
currentParams.pagename = pagename;
}
break;
case 'g18':
if (form['csd.g18_pagename']) {
var otherpage = form['csd.g18_pagename'].value;
if (!otherpage || !otherpage.trim()) {
alert(conv({ hans: 'CSD G18:请提供现有页面的名称。', hant: 'CSD G18:請提供現有頁面的名稱。' }));
parameters = null;
return false;
}
currentParams.pagename = otherpage;
}
break;
case 'f1':
if (form['csd.f1_filename']) {
redimage = form['csd.f1_filename'].value;
if (!redimage || !redimage.trim()) {
alert(conv({ hans: 'CSD F1:请提供另一文件的名称。', hant: 'CSD F1:請提供另一檔案的名稱。' }));
parameters = null;
return false;
}
currentParams.filename = redimage.replace(new RegExp('^\\s*' + Morebits.namespaceRegex(6) + ':', 'i'), '');
}
break;
case 'f5':
if (form['csd.f5_filename']) {
redimage = form['csd.f5_filename'].value;
if (!redimage || !redimage.trim()) {
alert(conv({ hans: 'CSD F5:请提供另一文件的名称。', hant: 'CSD F5:請提供另一檔案的名稱。' }));
parameters = null;
return false;
}
currentParams.filename = redimage.replace(new RegExp('^\\s*' + Morebits.namespaceRegex(6) + ':', 'i'), '');
}
break;
case 'f7':
if (form['csd.f7_filename']) {
var filename = form['csd.f7_filename'].value;
if (filename && filename !== Morebits.pageNameNorm) {
if (filename.indexOf('Image:') === 0 || filename.indexOf('File:') === 0 ||
filename.indexOf('文件:') === 0 || filename.indexOf('檔案:') === 0) {
currentParams['1'] = filename;
} else {
currentParams['1'] = 'File:' + filename;
}
}
}
break;
case 'r3':
if (form['csd.r3_type']) {
var redirtype = form['csd.r3_type'].value;
if (!redirtype) {
alert(conv({ hans: 'CSD R3:请选择适用类型。', hant: 'CSD R3:請選擇適用類別。' }));
parameters = null;
return false;
}
currentParams['1'] = redirtype;
}
break;
default:
break;
}
parameters.push(currentParams);
});
return parameters;
};
// function for processing talk page notification template parameters
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters) { // eslint-disable-line no-unused-vars
var utparams = [];
switch (normalized) {
default:
break;
}
return utparams;
};
Twinkle.speedy.resolveCsdValues = function twinklespeedyResolveCsdValues(e) {
var values = (e.target.form ? e.target.form : e.target).getChecked('csd');
if (values.length === 0) {
alert(conv({ hans: '请选择一个理据!', hant: '請選擇一個理據!' }));
return null;
}
return values;
};
Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e) {
var form = e.target.form ? e.target.form : e.target;
if (e.target.type === 'checkbox' || e.target.type === 'text' ||
e.target.type === 'select') {
return;
}
var tag_only = form.tag_only;
if (tag_only && tag_only.checked) {
Twinkle.speedy.callback.evaluateUser(e);
return;
}
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
return;
}
var normalizeds = values.map(function(value) {
return Twinkle.speedy.normalizeHash[value];
});
// analyse each criterion to determine whether to watch the page, prompt for summary, or open user talk page
var watchPage, promptForSummary;
normalizeds.forEach(function(norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = Twinkle.getPref('watchSpeedyExpiry');
}
if (Twinkle.getPref('promptForSpeedyDeletionSummary').indexOf(norm) !== -1) {
promptForSummary = true;
}
});
var params = {
values: values,
normalizeds: normalizeds,
watch: watchPage,
deleteTalkPage: form.talkpage && form.talkpage.checked,
deleteRedirects: form.redirects.checked,
openUserTalk: form.openusertalk.checked,
promptForSummary: promptForSummary,
templateParams: Twinkle.speedy.getParameters(form, values)
};
if (!params.templateParams) {
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Twinkle.speedy.callbacks.sysop.main(params);
};
Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
var form = e.target.form ? e.target.form : e.target;
if (e.target.type === 'checkbox' || e.target.type === 'text' ||
e.target.type === 'select') {
return;
}
var values = Twinkle.speedy.resolveCsdValues(e);
if (!values) {
return;
}
// var multiple = form.multiple.checked;
var normalizeds = [];
$.each(values, function(index, value) {
var norm = Twinkle.speedy.normalizeHash[value];
normalizeds.push(norm);
});
// analyse each criterion to determine whether to watch the page/notify the creator
var watchPage = false;
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('watchSpeedyPages').indexOf(norm) !== -1) {
watchPage = Twinkle.getPref('watchSpeedyExpiry');
return false; // break
}
});
var notifyuser = false;
if (form.notify.checked) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(norm) !== -1) {
notifyuser = true;
return false; // break
}
});
}
var welcomeuser = false;
if (notifyuser) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(norm) !== -1) {
welcomeuser = true;
return false; // break
}
});
}
var csdlog = false;
if (Twinkle.getPref('logSpeedyNominations')) {
$.each(normalizeds, function(index, norm) {
if (Twinkle.getPref('noLogOnSpeedyNomination').indexOf(norm) === -1) {
csdlog = true;
return false; // break
}
});
}
var params = {
values: values,
normalizeds: normalizeds,
watch: watchPage,
usertalk: notifyuser,
welcomeuser: welcomeuser,
lognomination: csdlog,
blank: form.blank.checked,
requestsalt: form.salting.checked,
templateParams: Twinkle.speedy.getParameters(form, values)
};
if (!params.templateParams) {
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '标记页面', hant: '標記頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};
Twinkle.addInitCallback(Twinkle.speedy, 'speedy');
})(jQuery);
// </nowiki>
8322bb535f18c528d0c5d237ee87c8af309e869f
MediaWiki:Gadget-twinklecopyvio.js
8
157
317
316
2024-08-03T04:07:22Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) { // eslint-disable-line no-unused-vars
/*
****************************************
*** twinklecopyvio.js: Copyvio module
****************************************
* Mode of invocation: Tab ("Copyvio")
* Active on: Existing, non-special pages, except for file pages with no local (non-Commons) file which are not redirects
* Config directives in: TwinkleConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.copyvio = function twinklecopyvio() {
// Disable on:
// * special pages
// * non-existent pages
// * files on Commons, whether there is a local page or not (unneeded local pages of files on Commons are eligible for CSD F2)
// * file pages without actual files (these are eligible for CSD G8)
if (mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && (document.getElementById('mw-sharedupload') || (!document.getElementById('mw-imagepage-section-filehistory') && !Morebits.isPageRedirect())))) {
return;
}
if (mw.config.get('wgPageContentModel') === 'flow-board') {
return;
}
Twinkle.addPortletLink(Twinkle.copyvio.callback, conv({ hans: '侵权', hant: '侵權' }), 'tw-copyvio', conv({ hans: '提报侵权页面', hant: '提報侵權頁面' }), '');
};
Twinkle.copyvio.callback = function twinklecopyvioCallback() {
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '提报侵权页面', hant: '提報侵權頁面' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '常见错误', hant: '常見錯誤' }), 'Wikipedia:管理员错误自查表/侵权处理');
Window.addFooterLink(conv({ hans: '侵权设置', hant: '侵權設定' }), 'WP:TW/PREF#copyvio');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#copyvio');
var form = new Morebits.quickForm(Twinkle.copyvio.callback.evaluate);
form.append({
type: 'textarea',
label: conv({ hans: '侵权来源:', hant: '侵權來源:' }),
name: 'source'
}
);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: 'CSD G5: 曾经根据侵权审核删除后又重新创建的内容', hant: 'CSD G5: 曾經根據侵權審核刪除後又重新建立的內容' }),
value: 'g5',
name: 'g5',
tooltip: conv({ hans: '同时以G5准则提报快速删除', hant: '同時以G5準則提報快速刪除' }),
subgroup: [{
name: 'g5_pagename',
type: 'input',
label: conv({ hans: '前次删除的页面名称', hant: '前次刪除的頁面名稱' }),
tooltip: conv({ hans: '选填,如果前次删除的页面名称不同,请提供', hant: '選填,如果前次刪除的頁面名稱不同,請提供' })
}]
},
{
label: conv({ hans: 'CSD G16: 页面与介绍相同事物的原页面同样侵权', hant: 'CSD G16: 頁面與介紹相同事物的原頁面同樣侵權' }),
value: 'g16',
name: 'g16',
tooltip: conv({ hans: '同时以G16准则提报快速删除', hant: '同時以G16準則提報快速刪除' }),
subgroup: [{
name: 'g16_pagename',
type: 'input',
label: conv({ hans: '已提报侵权的页面名称', hant: '已提報侵權的頁面名稱' }),
tooltip: conv({ hans: '必填,请提供当前正在侵权审核的页面名称,若页面已根据侵权删除,则应使用G5准则', hant: '必填,請提供目前正在侵權審核的頁面名稱,若頁面已根據侵權刪除,則應使用G5準則' })
}]
},
{
label: conv({ hans: '通知页面创建者', hant: '通知頁面建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '在页面创建者讨论页上放置一通知模板。', hant: '在頁面建立者討論頁上放置一通知模板。' }),
checked: true
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
};
Twinkle.copyvio.callbacks = {
tryTagging: function (pageobj) {
// 先尝试标记页面,如果发现已经标记则停止提报
var text = pageobj.getPageText();
if (text.indexOf('{{Copyvio|') === -1) {
Twinkle.copyvio.callbacks.taggingArticle(pageobj);
// Contributor specific edits
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'));
wikipedia_page.setCallbackParameters(pageobj.getCallbackParameters());
wikipedia_page.lookupCreation(Twinkle.copyvio.callbacks.main);
} else {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '页面已经标记侵权,请人工确认是否已经提报。', hant: '頁面已經標記侵權,請人工確認是否已經提報。' }));
}
},
main: function(pageobj) {
// this is coming in from lookupCreation...!
var params = pageobj.getCallbackParameters();
var initialContrib = pageobj.getCreator();
// Adding discussion
var wikipedia_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入侵权记录项', hant: '加入侵權記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.copyvio.callbacks.copyvioList);
// Notification to first contributor
if (params.notify) {
Morebits.wiki.flow.check('User talk:' + initialContrib, function () {
var flowpage = new Morebits.wiki.flow('User talk:' + initialContrib, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
var topic = '您建立的页面[[' + mw.config.get('wgPageName') + ']]可能侵犯版权';
var content = '{{subst:CopyvioNotice|' + mw.config.get('wgPageName') + '|flow=yes}}';
flowpage.setTopic(topic);
flowpage.setContent(content);
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + initialContrib + ')');
var notifytext = '\n{{subst:CopyvioNotice|' + mw.config.get('wgPageName') + '}}';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(conv({ hans: '通知:页面[[', hant: '通知:頁面[[' }) + mw.config.get('wgPageName') + conv({ hans: ']]疑似侵犯著作权', hant: ']]疑似侵犯版權' }));
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('copyvioWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
},
taggingArticle: function(pageobj) {
var params = pageobj.getCallbackParameters();
var revisionId = mw.config.get('wgRevisionId') || mw.config.get('wgDiffNewId') || mw.config.get('wgCurRevisionId');
var tag = '{{subst:Copyvio/auto|url=' + params.source.replace(/http/g, 'http').replace(/\n+/g, '\n').replace(/^\s*([^*])/gm, '* $1').replace(/^\* $/m, '') + '|OldRevision=' + revisionId + '}}';
var text = pageobj.getPageText();
var oldcsd = text.match(/{{\s*(db(-\w*)?|d|delete)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}/i);
if (oldcsd && confirm(conv({ hans: '在页面上找到快速删除模板,要保留吗?\n\n当页面同时侵犯著作权又符合快速删除标准时,应该优先走快速删除程序。\n单击“确认”以保留快速删除模板,若您认为快速删除理由不合,单击“取消”以移除快速删除模板。', hant: '在頁面上找到快速刪除模板,要保留嗎?\n\n當頁面同時侵犯版權又符合快速刪除標準時,應該優先走快速刪除程序。\n點擊「確認」以保留快速刪除模板,若您認為快速刪除理由不合,點擊「取消」以移除快速刪除模板。' }))) {
tag = oldcsd[0] + '\n' + tag;
var oldsalt = text.match(/{{\s*salt\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}/i);
if (oldsalt) {
tag = oldsalt[0] + '\n' + tag;
}
}
if (params.g5 || params.g16) {
var speedyTag = '{{delete';
if (params.g5) {
speedyTag += '|g5';
if (params.g5_pagename) {
speedyTag += '|' + params.g5_pagename + '|c1=[[Special:Undelete/' + params.g5_pagename + ']]';
} else {
speedyTag += '|c1=[[Special:Undelete/' + mw.config.get('wgPageName') + ']]';
}
}
if (params.g16) {
speedyTag += '|g16|' + params.g16_pagename;
}
speedyTag += '}}';
tag = speedyTag + '\n' + tag;
}
pageobj.setPageText(tag);
pageobj.setEditSummary(conv({ hans: '本页面疑似侵犯著作权', hant: '本頁面疑似侵犯版權' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('copyvioWatchPage'));
// pageobj.setCreateOption('recreate');
pageobj.save();
if (Twinkle.getPref('markCopyvioPagesAsPatrolled')) {
pageobj.patrol();
}
},
copyvioList: function(pageobj) {
var text = pageobj.getPageText();
var output = '';
var date = new Date();
var dateHeaderRegex = new RegExp('^===+\\s*' + (date.getUTCMonth() + 1) + '月' + date.getUTCDate() + '日' +
'\\s*===+', 'mg');
if (!dateHeaderRegex.exec(text)) {
output = '\n\n===' + (date.getUTCMonth() + 1) + '月' + date.getUTCDate() + '日' + '===';
}
output += '\n{{subst:CopyvioVFDRecord|' + mw.config.get('wgPageName') + '}}';
pageobj.setAppendText(output);
pageobj.setEditSummary('加入[[' + mw.config.get('wgPageName') + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
}
};
Twinkle.copyvio.callback.evaluate = function(e) {
var params = Morebits.quickForm.getInputData(e.target);
if (!params.source.trim()) {
alert(conv({ hans: '请指定侵权来源', hant: '請指定侵權來源' }));
return;
}
if (params.g16 && !params.g16_pagename.trim()) {
alert(conv({ hans: '请提供G16已提报侵权的页面名称', hant: '請提供G16已提報侵權的頁面名稱' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
params.logpage = 'Wikipedia:頁面存廢討論/疑似侵權';
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '提报完成,将在几秒内刷新页面', hant: '提報完成,將在幾秒內重新整理頁面' });
// Tagging file
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入侵权模板到页面', hant: '加入侵權模板到頁面' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.copyvio.callbacks.tryTagging);
Morebits.wiki.removeCheckpoint();
};
Twinkle.addInitCallback(Twinkle.copyvio, 'copyvio');
})(jQuery);
// </nowiki>
75a468d750ba5fdcaadc0ac92f4437b7e01f7840
MediaWiki:Gadget-twinklexfd.js
8
158
319
318
2024-08-03T04:07:23Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklexfd.js: XFD module
****************************************
* Mode of invocation: Tab ("XFD")
* Active on: Existing, non-special pages, except for file pages with no local (non-Commons) file which are not redirects
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.xfd = function twinklexfd() {
// Disable on:
// * special pages
// * Flow pages
// * non-existent pages
// * files on Commons, whether there is a local page or not (unneeded local pages of files on Commons are eligible for CSD F2)
// * file pages without actual files (these are eligible for CSD G8)
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && (document.getElementById('mw-sharedupload') || (!document.getElementById('mw-imagepage-section-filehistory') && !Morebits.isPageRedirect())))) {
return;
}
Twinkle.addPortletLink(Twinkle.xfd.callback, conv({ hans: '提删', hant: '提刪' }), 'tw-xfd', conv({ hans: '提交删除讨论', hant: '提交刪除討論' }));
};
Twinkle.xfd.currentRationale = null;
// error callback on Morebits.status.object
Twinkle.xfd.printRationale = function twinklexfdPrintRationale() {
if (Twinkle.xfd.currentRationale) {
Morebits.status.printUserText(Twinkle.xfd.currentRationale, conv({ hans: '您的理由已在下方提供,如果您想重新提交,请将其复制到一新窗口中:', hant: '您的理由已在下方提供,如果您想重新提交,請將其複製到一新視窗中:' }));
// only need to print the rationale once
Twinkle.xfd.currentRationale = null;
}
};
Twinkle.xfd.callback = function twinklexfdCallback() {
var Window = new Morebits.simpleWindow(600, 350);
Window.setTitle(conv({ hans: '提交存废讨论', hant: '提交存廢討論' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '关于存废讨论', hant: '關於存廢討論' }), 'WP:XFD');
Window.addFooterLink(conv({ hans: '提删设置', hant: '提刪設定' }), 'WP:TW/PREF#xfd');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#xfd');
var form = new Morebits.quickForm(Twinkle.xfd.callback.evaluate);
var categories = form.append({
type: 'select',
name: 'category',
label: conv({ hans: '提交类型:', hant: '提交類別:' }),
event: Twinkle.xfd.callback.change_category
});
categories.append({
type: 'option',
label: conv({ hans: '页面存废讨论', hant: '頁面存廢討論' }),
selected: mw.config.get('wgNamespaceNumber') === 0, // Main namespace
value: 'afd'
});
categories.append({
type: 'option',
label: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' }),
selected: mw.config.get('wgNamespaceNumber') === 6, // File namespace
value: 'ffd'
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,通知页面创建者', hant: '如可能,通知頁面建立者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '在页面创建者讨论页上放置一通知模板。', hant: '在頁面建立者討論頁上放置一通知模板。' }),
checked: true
}
]
}
);
form.append({
type: 'field',
label: '工作区',
name: 'work_area'
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
if (mw.config.get('wgPageContentModel') !== 'wikitext') {
form = new Morebits.quickForm(Twinkle.xfd.callback.evaluate);
form.append({
type: 'div',
label: [
conv({ hans: 'Twinkle不支持在页面内容模型为', hant: 'Twinkle不支援在頁面內容模型為' }),
mw.config.get('wgPageContentModel'),
conv({ hans: '的页面上挂上存废讨论模板,请参见', hant: '的頁面上掛上存廢討論模板,請參見' }),
$('<a>').attr({ target: '_blank', href: mw.util.getUrl('WP:SPECIALSD') }).text(conv({ hans: '手动放置模板时的注意事项', hant: '手動放置模板時的注意事項' }))[0],
'。'
]
});
Window.setContent(form.render());
Window.display();
return;
}
// We must init the controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.category.dispatchEvent(evt);
};
Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory(e) {
var value = e.target.value;
var form = e.target.form;
var old_area = Morebits.quickForm.getElements(e.target.form, 'work_area')[0];
var work_area = null;
var oldreasontextbox = form.getElementsByTagName('textarea')[0];
var oldreason = oldreasontextbox ? oldreasontextbox.value : '';
var appendReasonBox = function twinklexfdAppendReasonBox(xfd_cat) {
switch (xfd_cat) {
case 'fwdcsd':
oldreason = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
break;
case 'fame':
oldreason = Twinkle.getPref('afdFameDefaultReason');
break;
case 'substub':
oldreason = Twinkle.getPref('afdSubstubDefaultReason');
break;
default:
break;
}
work_area.append({
type: 'textarea',
name: 'xfdreason',
label: conv({ hans: '提删理由:', hant: '提刪理由:' }),
value: oldreason,
tooltip: conv({ hans: '您可以使用维基格式,Twinkle将自动为您加入签名。如果您使用批量提删功能,存废讨论页只会使用第一次提交的理由,但之后您仍需提供以用于删除通告模板的参数。', hant: '您可以使用維基格式,Twinkle將自動為您加入簽名。如果您使用批次提刪功能,存廢討論頁只會使用第一次提交的理由,但之後您仍需提供以用於刪除通告模板的參數。' }),
placeholder: conv({ hans: '此值亦显示于页面的删除通告模板内,故务必提供此值,避免使用“同上”等用语。', hant: '此值亦顯示於頁面的刪除通告模板內,故務必提供此值,避免使用「同上」等用語。' })
});
// TODO possible future "preview" link here
};
switch (value) {
case 'afd':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '页面存废讨论', hant: '頁面存廢討論' }),
name: 'work_area'
});
work_area.append({
type: 'checkbox',
list: [
{
label: '使用<noinclude>包裹模板',
value: 'noinclude',
name: 'noinclude',
checked: mw.config.get('wgNamespaceNumber') === 10, // Template namespace
tooltip: conv({ hans: '使其不会在被包含时出现。', hant: '使其不會在被包含時出現。' })
}
]
});
var afd_category = work_area.append({
type: 'select',
name: 'xfdcat',
label: conv({ hans: '选择提删类型:', hant: '選擇提刪類別:' }),
event: Twinkle.xfd.callback.change_afd_category
});
var afd_cat = 'delete';
if (Twinkle.getPref('afdDefaultCategory') === 'same') {
if (localStorage.Twinkle_afdCategory === undefined) {
localStorage.Twinkle_afdCategory = 'delete';
} else {
afd_cat = localStorage.Twinkle_afdCategory;
}
}
afd_category.append({ type: 'option', label: conv({ hans: '删除', hant: '刪除' }), value: 'delete', selected: afd_cat === 'delete' });
afd_category.append({ type: 'option', label: conv({ hans: '合并', hant: '合併' }), value: 'merge', selected: afd_cat === 'merge' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基词典', hant: '移動到維基詞典' }), value: 'vmd', selected: afd_cat === 'vmd' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基文库', hant: '移動到維基文庫' }), value: 'vms', selected: afd_cat === 'vms' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' }), value: 'vmb', selected: afd_cat === 'vmb' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基语录', hant: '移動到維基語錄' }), value: 'vmq', selected: afd_cat === 'vmq' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基导游', hant: '移動到維基導遊' }), value: 'vmvoy', selected: afd_cat === 'vmvoy' });
afd_category.append({ type: 'option', label: conv({ hans: '移动到维基学院', hant: '移動到維基學院' }), value: 'vmv', selected: afd_cat === 'vmv' });
if (Twinkle.getPref('FwdCsdToXfd')) {
afd_category.append({ type: 'option', label: conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' }), value: 'fwdcsd', selected: afd_cat === 'fwdcsd' });
}
afd_category.append({ type: 'option', label: conv({ hans: '批量关注度提删', hant: '批次關注度提刪' }), value: 'fame', selected: afd_cat === 'fame' });
afd_category.append({ type: 'option', label: conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' }), value: 'substub', selected: afd_cat === 'substub' });
afd_category.append({ type: 'option', label: conv({ hans: '批量其他提删', hant: '批次其他提刪' }), value: 'batch', selected: afd_cat === 'batch' });
work_area.append({
type: 'input',
name: 'mergeinto',
label: conv({ hans: '合并到:', hant: '合併到:' }),
hidden: true
});
appendReasonBox(afd_cat);
work_area.append({
type: 'textarea',
name: 'fwdcsdreason',
label: conv({ hans: '转交理由:', hant: '轉交理由:' }),
tooltip: conv({ hans: '您可以使用维基格式,Twinkle将自动为您加入签名。', hant: '您可以使用維基格式,Twinkle將自動為您加入簽名。' }),
hidden: true
});
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
form.xfdcat.dispatchEvent(evt);
break;
case 'ffd':
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' }),
name: 'work_area'
});
appendReasonBox('ffd');
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
default:
work_area = new Morebits.quickForm.element({
type: 'field',
label: conv({ hans: '未定义', hant: '未定義' }),
name: 'work_area'
});
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
break;
}
// Return to checked state when switching
form.notify.checked = true;
form.notify.disabled = false;
};
Twinkle.xfd.getAfdBatchReason = function twinklexfdGetAfdBatchReason() {
var previousTime = parseInt(localStorage.getItem('Twinkle_afdBatchReasonTime'));
if (previousTime && new Date() - new Date(previousTime) < 1000 * 60 * 60) {
return localStorage.getItem('Twinkle_afdBatchReasonText') || '';
}
return '';
};
Twinkle.xfd.callback.change_afd_category = function twinklexfdCallbackChangeAfdCategory(e) {
if (e.target.value === 'merge') {
e.target.form.mergeinto.parentElement.removeAttribute('hidden');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.mergeinto.previousElementSibling.innerHTML = conv({ hans: '合并到:', hant: '合併到:' });
} else if (e.target.value === 'fwdcsd') {
e.target.form.mergeinto.parentElement.removeAttribute('hidden');
e.target.form.fwdcsdreason.parentElement.removeAttribute('hidden');
e.target.form.mergeinto.previousElementSibling.innerHTML = '提交人:';
e.target.form.xfdreason.value = decodeURIComponent($('#delete-reason').text()).replace(/\+/g, ' ');
} else if (e.target.value === 'fame') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.getPref('afdFameDefaultReason');
} else if (e.target.value === 'substub') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.getPref('afdSubstubDefaultReason');
} else if (e.target.value === 'batch') {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
e.target.form.xfdreason.value = Twinkle.xfd.getAfdBatchReason();
} else {
e.target.form.mergeinto.parentElement.setAttribute('hidden', '');
e.target.form.fwdcsdreason.parentElement.setAttribute('hidden', '');
}
if (Twinkle.getPref('afdDefaultCategory') === 'same') {
localStorage.Twinkle_afdCategory = e.target.value;
}
};
Twinkle.xfd.callbacks = {
afd: {
main: function(tagging_page) {
var params = tagging_page.getCallbackParameters();
Twinkle.xfd.callbacks.afd.taggingArticle(tagging_page);
// Adding discussion
var discussion_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入讨论到当日列表', hant: '加入討論到當日列表' }));
discussion_page.setFollowRedirect(true);
discussion_page.setCallbackParameters(params);
discussion_page.load(Twinkle.xfd.callbacks.afd.todaysList);
// Notification to first contributor
if (params.notify) {
// Disallow warning yourself
if (params.creator === mw.config.get('wgUserName')) {
Morebits.status.warn(conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')', conv({ hans: '您创建了该页,跳过通知', hant: '您建立了該頁,跳過通知' }));
params.creator = null;
} else {
var talkPageName = 'User talk:' + params.creator;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
flowpage.setTopic('页面[[:' + Morebits.pageNameNorm + ']]存废讨论通知');
flowpage.setContent('{{subst:AFDNote|' + Morebits.pageNameNorm + '|flow=yes}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
var notifytext = '\n{{subst:AFDNote|' + Morebits.pageNameNorm + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary('通知:页面[[' + Morebits.pageNameNorm + ']]存废讨论提名');
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('xfdWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, params.creator);
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, null);
}
},
taggingArticle: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var tag = '{{vfd|' + Morebits.string.formatReasonText(params.xfdreason);
switch (params.xfdcat) {
case 'vmd':
tag += '|wikt';
break;
case 'vms':
tag += '|s';
break;
case 'vmb':
tag += '|b';
break;
case 'vmq':
tag += '|q';
break;
case 'vmvoy':
tag += '|voy';
break;
case 'vmv':
tag += '|v';
break;
default:
break;
}
if (Morebits.isPageRedirect()) {
tag += '|r';
}
tag += '|date={{subst:#time:Y/m/d}}}}';
if (params.noinclude) {
tag = '<noinclude>' + tag + '</noinclude>';
// 只有表格需要单独加回车,其他情况加回车会破坏模板。
if (text.indexOf('{|') === 0) {
tag += '\n';
}
} else {
tag += '\n';
}
// Then, test if there are speedy deletion-related templates on the article.
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|(?:hang|hold)[- ]?on)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && confirm(conv({ hans: '在页面上找到快速删除模板,要移除吗?', hant: '在頁面上找到快速刪除模板,要移除嗎?' }))) {
text = textNoSd;
}
var textNoNotMandarin = text.replace(/\{\{\s*(NotMandarin|Notchinese|非中文|非現代漢語|非现代汉语|非現代標準漢語|非现代标准汉语)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoNotMandarin && confirm(conv({ hans: '在页面上找到非现代标准汉语模板,要移除吗?', hant: '在頁面上找到非現代標準漢語模板,要移除嗎?' }))) {
text = textNoNotMandarin;
}
var textNoAfc = text.replace(/{{\s*AFC submission\s*\|\s*\|[^}]*?}}\s*/ig, '');
if (text !== textNoAfc && confirm(conv({ hans: '在页面上找到AFC提交模板,要移除吗?', hant: '在頁面上找到AFC提交模板,要移除嗎?' }))) {
text = textNoAfc;
}
// Mark the page as patrolled, if wanted
if (Twinkle.getPref('markXfdPagesAsPatrolled')) {
pageobj.patrol();
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '页面存废讨论:[[', hant: '頁面存廢討論:[[' }) + params.logpage + '#' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchPage'));
pageobj.save();
},
todaysList: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var type = '';
var to = '';
switch (params.xfdcat) {
case 'vmd':
case 'vms':
case 'vmb':
case 'vmq':
case 'vmvoy':
case 'vmv':
type = 'vm';
to = params.xfdcat;
break;
case 'fwdcsd':
case 'merge':
to = params.mergeinto;
/* Fall through */
default:
type = params.xfdcat;
break;
}
var append = true;
switch (type) {
case 'fame':
case 'substub':
case 'batch':
var commentText = '<!-- Twinkle: User:' + mw.config.get('wgUserName') + ' 的 ' + type + ' 提刪插入點,請勿變更或移除此行,除非不再於此頁提刪 -->';
var newText = '===[[:' + Morebits.pageNameNorm + ']]===';
if (type === 'fame') {
newText += '\n{{Findsources|' + Morebits.pageNameNorm + '}}';
}
if (text.indexOf(commentText) !== -1) {
text = text.replace(commentText, newText + '\n\n' + commentText);
pageobj.setPageText(text);
append = false;
} else {
var appendText = '\n{{safesubst:SafeAfdHead}}\n' +
{
fame: '==30天后仍掛有{{tl|notability}}模板的條目==\n' +
'<span style="font-size:smaller;">(已掛[[template:notability|關注度模板]]30天)</span>',
substub: '==到期篩選的小小作品==',
batch: '==批量提刪=='
}[type] + '\n' +
newText + '\n\n' +
commentText + '\n' +
'----\n' +
':{{删除}}理據:' + Morebits.string.formatReasonText(params.xfdreason) + '\n' +
'提报以上' + {
fame: '<u>关注度不足</u>条目',
substub: '<u>小小作品</u>',
batch: '頁面'
}[type] + '的維基人及時間:<br id="no-new-title" />~~~~';
pageobj.setAppendText(appendText);
}
break;
default:
pageobj.setAppendText('\n{{subst:DRItem|Type=' + type + '|DRarticles=' + Morebits.pageNameNorm + '|Reason=' + Morebits.string.formatReasonText(params.xfdreason) + (params.fwdcsdreason.trim() !== '' ? '<br>\n轉交理由:' + params.fwdcsdreason : '') + '|To=' + to + '}}~~~~');
break;
}
pageobj.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ 新提案');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchDiscussion'));
pageobj.setCreateOption('recreate');
if (append) {
pageobj.append();
} else {
pageobj.save();
}
Twinkle.xfd.currentRationale = null; // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
},
lookupCreation: function (target_page) {
target_page.getStatusElement().info('完成');
var params = target_page.getCallbackParameters();
params.creator = target_page.getCreator();
// Tagging page
var tagging_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入存废讨论模板到页面', hant: '加入存廢討論模板到頁面' }));
tagging_page.setFollowRedirect(false);
tagging_page.setCallbackParameters(params);
tagging_page.load(Twinkle.xfd.callbacks.afd.tryTagging);
},
tryTagging: function (tagging_page) {
var statelem = tagging_page.getStatusElement();
// defaults to /doc for lua modules, which may not exist
if (!tagging_page.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = tagging_page.getPageText();
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想继续提报?', hant: '}}已被置於頁面中,您是否仍想繼續提報?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
var copyvio = /(?:\{\{\s*(copyvio)[^{}]*?\}\})/i.exec(text);
if (copyvio) {
statelem.error(conv({ hans: '页面中已有著作权验证模板。', hant: '頁面中已有著作權驗證模板。' }));
return;
}
Twinkle.xfd.callbacks.afd.main(tagging_page);
}
},
ffd: {
main: function(tagging_page) {
var params = tagging_page.getCallbackParameters();
Twinkle.xfd.callbacks.ffd.taggingImage(tagging_page);
// Adding discussion
var wikipedia_page = new Morebits.wiki.page(params.logpage, conv({ hans: '加入讨论到当日列表', hant: '加入討論到當日列表' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.xfd.callbacks.ffd.todaysList);
// Notification to first contributor
if (params.notify) {
// Disallow warning yourself
if (params.creator === mw.config.get('wgUserName')) {
Morebits.status.warn(conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')', conv({ hans: '您创建了该页,跳过通知', hant: '您建立了該頁,跳過通知' }));
return;
}
var talkPageName = 'User talk:' + params.creator;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
flowpage.setTopic('文件[[:File:' + mw.config.get('wgTitle') + ']]存废讨论通知');
flowpage.setContent('{{subst:idw|File:' + mw.config.get('wgTitle') + '|flow=yes}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知页面创建者(', hant: '通知頁面建立者(' }) + params.creator + ')');
var notifytext = '\n{{subst:idw|File:' + mw.config.get('wgTitle') + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary('通知:文件[[' + Morebits.pageNameNorm + ']]存废讨论提名');
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('xfdWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, params.creator);
}
// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
} else if (params.lognomination) {
Twinkle.xfd.callbacks.addToLog(params, null);
}
},
taggingImage: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
pageobj.setPageText('{{ifd|' + Morebits.string.formatReasonText(params.xfdreason) + '|date={{subst:#time:Y/m/d}}}}\n' + text);
pageobj.setEditSummary(conv({ hans: '文件存废讨论:[[', hant: '檔案存廢討論:[[' }) + params.logpage + '#' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchPage'));
pageobj.setCreateOption('recreate'); // it might be possible for a file to exist without a description page
pageobj.save();
},
todaysList: function(pageobj) {
// var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
pageobj.setAppendText('\n{{subst:IfdItem|Filename=' + mw.config.get('wgTitle') + '|Uploader=' + params.creator + '|Reason=' + Morebits.string.formatReasonText(params.xfdreason) + '}}--~~~~');
pageobj.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ 新提案');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('xfdWatchDiscussion'));
pageobj.setCreateOption('recreate');
pageobj.append(function() {
Twinkle.xfd.currentRationale = null; // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
});
},
lookupCreation: function (target_page) {
target_page.getStatusElement().info('完成');
var params = target_page.getCallbackParameters();
params.creator = target_page.getCreator();
// Tagging file
var tagging_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入存废讨论模板到文件描述页', hant: '加入存廢討論模板到檔案描述頁' }));
tagging_page.setFollowRedirect(false);
tagging_page.setCallbackParameters(params);
tagging_page.load(Twinkle.xfd.callbacks.ffd.tryTagging);
},
tryTagging: function (tagging_page) {
var statelem = tagging_page.getStatusElement();
if (!tagging_page.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = tagging_page.getPageText();
var xfd = /(?:\{\{([rsaiftcmv]fd|md1|proposed deletion)[^{}]*?\}\})/i.exec(text);
if (xfd && !confirm(conv({ hans: '删除相关模板{{', hant: '刪除相關模板{{' }) + xfd[1] + conv({ hans: '}}已被置于页面中,您是否仍想继续提报?', hant: '}}已被置於頁面中,您是否仍想繼續提報?' }))) {
statelem.error(conv({ hans: '页面已被提交至存废讨论。', hant: '頁面已被提交至存廢討論。' }));
return;
}
Twinkle.xfd.callbacks.ffd.main(tagging_page);
}
},
addToLog: function(params, initialContrib) {
var editsummary = conv({ hans: '记录对[[', hant: '記錄對[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的存废讨论提名', hant: ']]的存廢討論提名' });
var usl = new Morebits.userspaceLogger(Twinkle.getPref('xfdLogPageName'));
usl.initialText =
conv({
hans: '这是该用户使用[[WP:TW|Twinkle]]的提删模块做出的[[WP:XFD|存废讨论]]提名列表。\n\n' +
'如果您不再想保留此日志,请在[[' + Twinkle.getPref('configPage') + '|参数设置]]中关掉,并' +
'使用[[WP:CSD#O1|CSD O1]]提交快速删除。',
hant: '這是該使用者使用[[WP:TW|Twinkle]]的提刪模塊做出的[[WP:XFD|存廢討論]]提名列表。\n\n' +
'如果您不再想保留此日誌,請在[[' + Twinkle.getPref('configPage') + '|偏好設定]]中關掉,並' +
'使用[[WP:CSD#O1|CSD O1]]提交快速刪除。'
});
var xfdCatName;
switch (params.xfdcat) {
case 'delete':
xfdCatName = conv({ hans: '删除', hant: '刪除' });
break;
case 'merge':
xfdCatName = conv({ hans: '合并到', hant: '合併到' });
break;
case 'vmd':
xfdCatName = conv({ hans: '移动到维基词典', hant: '移動到維基詞典' });
break;
case 'vms':
xfdCatName = conv({ hans: '移动到维基文库', hant: '移動到維基文庫' });
break;
case 'vmb':
xfdCatName = conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' });
break;
case 'vmq':
xfdCatName = conv({ hans: '移动到维基语录', hant: '移動到維基語錄' });
break;
case 'vmvoy':
xfdCatName = conv({ hans: '移动到维基导游', hant: '移動到維基導遊' });
break;
case 'vmv':
xfdCatName = conv({ hans: '移动到维基学院', hant: '移動到維基學院' });
break;
case 'fwdcsd':
xfdCatName = conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' });
break;
case 'fame':
xfdCatName = conv({ hans: '批量关注度提删', hant: '批次關注度提刪' });
break;
case 'substub':
xfdCatName = conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' });
break;
case 'batch':
xfdCatName = conv({ hans: '批量其他提删', hant: '批次其他提刪' });
break;
default:
xfdCatName = conv({ hans: '文件存废讨论', hant: '檔案存廢討論' });
break;
}
// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
var appendText = '# [[:' + Morebits.pageNameNorm + ']]';
if (mw.config.get('wgNamespaceNumber') === 6) {
appendText += '([{{fullurl:Special:Log|page=' + mw.util.wikiUrlencode(mw.config.get('wgPageName')) + '}} ' + conv({ hans: '日志', hant: '日誌' }) + '])';
}
appendText += ':' + xfdCatName;
if (params.xfdcat === 'merge') {
appendText += '[[:' + params.mergeinto + ']]';
}
appendText += '。';
if (params.xfdreason) {
appendText += "'''" + (params.xfdcat === 'fwdcsd' ? conv({ hans: '原删除理据', hant: '原刪除理據' }) : conv({ hans: '理据', hant: '理據' })) + "''':" + Morebits.string.formatReasonForLog(params.xfdreason);
appendText = Morebits.string.appendPunctuation(appendText);
}
if (params.fwdcsdreason) {
appendText += "'''" + (params.xfdcat === 'fwdcsd' ? conv({ hans: '转交理据', hant: '轉交理據' }) : conv({ hans: '理据', hant: '理據' })) + "''':" + Morebits.string.formatReasonForLog(params.fwdcsdreason);
appendText = Morebits.string.appendPunctuation(appendText);
}
if (initialContrib) {
appendText += ';通知{{user|' + initialContrib + '}}';
}
appendText += ' ~~~~~\n';
usl.changeTags = Twinkle.changeTags;
usl.log(appendText, editsummary);
}
};
Twinkle.xfd.callback.evaluate = function(e) {
var params = Morebits.quickForm.getInputData(e.target);
if (params.xfdcat === 'merge' && params.mergeinto.trim() === '') {
alert(conv({ hans: '请提供合并目标!', hant: '請提供合併目標!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Twinkle.xfd.currentRationale = params.xfdreason;
Morebits.status.onError(Twinkle.xfd.printRationale);
if (!params.category) {
Morebits.status.error('错误', '未定义的动作');
return;
}
var target_page;
var date = new Morebits.date(); // XXX: avoid use of client clock, still used by TfD, FfD and CfD
switch (params.category) {
case 'afd': // AFD
if (params.xfdcat === 'batch') {
localStorage.setItem('Twinkle_afdBatchReasonText', params.xfdreason || '');
localStorage.setItem('Twinkle_afdBatchReasonTime', new Date().getTime());
}
params.logpage = 'Wikipedia:頁面存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc');
params.lognomination = Twinkle.getPref('logXfdNominations') && Twinkle.getPref('noLogOnXfdNomination').indexOf(params.xfdcat) === -1;
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = params.logpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
// Lookup creation
target_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '获取页面创建信息', hant: '取得頁面建立資訊' }));
target_page.setCallbackParameters(params);
if (mw.config.get('wgPageContentModel') === 'wikitext') {
target_page.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
}
target_page.lookupCreation(Twinkle.xfd.callbacks.afd.lookupCreation);
Morebits.wiki.removeCheckpoint();
break;
case 'ffd': // FFD
params.logpage = 'Wikipedia:檔案存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc');
params.lognomination = Twinkle.getPref('logXfdNominations') && Twinkle.getPref('noLogOnXfdNomination').indexOf('ffd') === -1;
Morebits.wiki.addCheckpoint();
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = params.logpage;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
// Lookup creation
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '获取页面创建信息', hant: '取得頁面建立資訊' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
wikipedia_page.lookupCreation(Twinkle.xfd.callbacks.ffd.lookupCreation);
Morebits.wiki.removeCheckpoint();
break;
default:
alert('twinklexfd:未定义的类别');
break;
}
};
Twinkle.addInitCallback(Twinkle.xfd, 'xfd');
})(jQuery);
// </nowiki>
99738e5e0724b0c6617ef148941f7cb54a389647
MediaWiki:Gadget-twinkleimage.js
8
159
321
320
2024-08-03T04:07:24Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) { // eslint-disable-line no-unused-vars
/*
****************************************
*** twinkleimage.js: Image CSD module
****************************************
* Mode of invocation: Tab ("DI")
* Active on: Local nonredirect file pages (not on Commons)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.image = function twinkleimage() {
if (mw.config.get('wgNamespaceNumber') === 6 &&
!document.getElementById('mw-sharedupload') &&
document.getElementById('mw-imagepage-section-filehistory')) {
Twinkle.addPortletLink(Twinkle.image.callback, conv({ hans: '图权', hant: '圖權' }), 'tw-di', conv({ hans: '提交文件快速删除', hant: '提交檔案快速刪除' }));
}
};
Twinkle.image.callback = function twinkleimageCallback() {
var Window = new Morebits.simpleWindow(600, 330);
Window.setTitle(conv({ hans: '文件快速删除候选', hant: '檔案快速刪除候選' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '快速删除方针', hant: '快速刪除方針' }), 'WP:CSD');
Window.addFooterLink(conv({ hans: '图权设置', hant: '圖權設定' }), 'WP:TW/PREF#image');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#image');
var form = new Morebits.quickForm(Twinkle.image.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '通知上传者', hant: '通知上傳者' }),
value: 'notify',
name: 'notify',
tooltip: conv({ hans: '如果您在标记同一用户的很多文件,请取消此复选框以避免发送过多消息。CSD F6永远不会通知。', hant: '如果您在標記同一使用者的很多檔案,請取消此核取方塊以避免發送過多訊息。CSD F6永遠不會通知。' }),
checked: Twinkle.getPref('notifyUserOnDeli')
}
]
}
);
var field = form.append({
type: 'field',
label: conv({ hans: '需要的动作', hant: '需要的動作' })
});
field.append({
type: 'radio',
name: 'type',
list: [
{
label: conv({ hans: '来源不明(CSD F3)', hant: '來源不明(CSD F3)' }),
value: 'no source',
checked: true,
tooltip: conv({ hans: '本文件并未注明原始出处', hant: '本檔案並未註明原始出處' })
},
{
label: conv({ hans: '未知著作权或著作权无法被查证(CSD F4)', hant: '未知著作權或著作權無法被查證(CSD F4)' }),
value: 'no license',
tooltip: conv({ hans: '本文件缺少著作权信息,或声称的著作权信息无法被查证', hant: '本檔案缺少著作權資訊,或聲稱的著作權資訊無法被查證' })
},
{
label: conv({ hans: '来源不明(CSD F3)且未知著作权或著作权无法被查证(CSD F4)', hant: '來源不明(CSD F3)且未知著作權或著作權無法被查證(CSD F4)' }),
value: 'no source no license',
tooltip: conv({ hans: '本文件并未注明原始出处,且本文件缺少著作权信息或声称的著作权信息无法被查证', hant: '本檔案並未註明原始出處,且本檔案缺少著作權資訊或聲稱的著作權資訊無法被查證' })
},
{
label: conv({ hans: '没有被条目使用的非自由著作权文件(CSD F6)', hant: '沒有被條目使用的非自由著作權檔案(CSD F6)' }),
value: 'orphaned fair use',
tooltip: conv({ hans: '本文件为非自由著作权且没有被条目使用', hant: '本檔案為非自由著作權且沒有被條目使用' })
},
{
label: conv({ hans: '明显侵权之文件(CSD F8)', hant: '明顯侵權之檔案(CSD F8)' }),
value: 'no permission',
tooltip: conv({ hans: '上传者宣称拥有,而在其他来源找到的文件。或从侵权的来源获取的文件。', hant: '上傳者宣稱擁有,而在其他來源找到的檔案。或從侵權的來源取得的檔案。' }),
subgroup: {
name: 'f8_source',
type: 'textarea',
label: conv({ hans: '侵权来源:', hant: '侵權來源:' })
}
},
{
label: conv({ hans: '没有填写任何合理使用依据的非自由著作权文件(CSD F9)', hant: '沒有填寫任何合理使用依據的非自由著作權檔案(CSD F9)' }),
value: 'no fair use rationale',
tooltip: conv({ hans: '不适用于有争议但完整的合理使用依据。如果非自由著作权文件只有部分条目的使用依据,但同时被使用于未提供合理使用依据的条目,则本方针也不适用。', hant: '不適用於有爭議但完整的合理使用依據。如果非自由著作權檔案只有部分條目的使用依據,但同時被使用於未提供合理使用依據的條目,則本方針也不適用。' })
},
{
label: conv({ hans: '可被替代的非自由著作权文件(CSD F10)', hant: '可被替代的非自由著作權檔案(CSD F10)' }),
value: 'replaceable fair use',
tooltip: conv({ hans: '文件仅用于描述、识别或评论文件中展示的事物,或仅用作插图,且满足以下四个条件之一。如果给出了其他合理使用依据,不适用本条。如对文件的可替代性存在争议,应交文件存废讨论处理。本条也不适用于正在或曾经由文件存废讨论处理过的文件。', hant: '檔案僅用於描述、辨識或評論檔案中展示的事物,或僅用作插圖,且滿足以下四個條件之一。如果給出了其他合理使用依據,不適用本條。如對檔案的可替代性存在爭議,應交檔案存廢討論處理。本條也不適用於正在或曾經由檔案存廢討論處理過的檔案。' }),
subgroup: {
name: 'f10_type',
type: 'select',
label: conv({ hans: '适用类型:', hant: '適用類別:' }),
style: 'width: 85%;',
list: [
{ label: conv({ hans: '请选择', hant: '請選擇' }), value: '' },
{ label: conv({ hans: '有其他自由著作权文件展示相同的事物', hant: '有其他自由著作權檔案展示相同的事物' }), value: '1' },
{ label: conv({ hans: '文件描述的是在世或假定在世人物、仍然存在的建筑、室外雕塑或仍然在售的商品,且预计自行拍摄的照片不受他人著作权保护', hant: '檔案描述的是在世或假定在世人物、仍然存在的建築、室外雕塑或仍然在售的商品,且預計自行拍攝的相片不受他人著作權保護' }), value: '2' },
{ label: conv({ hans: '文件为可自行绘制的地图或图表', hant: '檔案為可自行繪製的地圖或圖表' }), value: '3' },
{ label: conv({ hans: '文件来自商业图片机构(如Getty)', hant: '檔案來自商業圖片機構(如Getty)' }), value: '4' }
]
}
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the parameters
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.type[0].dispatchEvent(evt);
};
Twinkle.image.callback.evaluate = function twinkleimageCallbackEvaluate(event) {
var type;
var notify = event.target.notify.checked;
var types = event.target.type;
for (var i = 0; i < types.length; ++i) {
if (types[i].checked) {
type = types[i].values;
break;
}
}
var csdcrit;
switch (type) {
case 'no source':
csdcrit = 'f3';
break;
case 'no license':
csdcrit = 'f4';
break;
case 'no source no license':
csdcrit = 'f3 f4';
break;
case 'orphaned fair use':
csdcrit = 'f6';
notify = false;
break;
case 'no permission':
csdcrit = 'f8';
break;
case 'no fair use rationale':
csdcrit = 'f9';
break;
case 'replaceable fair use':
csdcrit = 'f10';
break;
default:
throw new Error('Twinkle.image.callback.evaluate:未知条款');
}
var lognomination = Twinkle.getPref('logSpeedyNominations') && Twinkle.getPref('noLogOnSpeedyNomination').indexOf(csdcrit.toLowerCase()) === -1;
var templatename = type;
var params = {
type: type,
templatename: templatename,
normalized: csdcrit,
lognomination: lognomination
};
if (csdcrit === 'f8') {
params.f8_source = event.target['type.f8_source'].value;
}
if (csdcrit === 'f10') {
var f10_type = event.target['type.f10_type'].value;
if (!f10_type) {
alert(conv({ hans: 'CSD F10:请选择适用类型。', hant: 'CSD F10:請選擇適用類別。' }));
return false;
}
params.f10_type = f10_type;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(event.target);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
// Tagging image
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '加入删除标记', hant: '加入刪除標記' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.image.callbacks.taggingImage);
// Notifying uploader
if (notify) {
wikipedia_page.lookupCreation(Twinkle.image.callbacks.userNotification);
} else {
// add to CSD log if desired
if (lognomination) {
params.fromDI = true;
Twinkle.speedy.callbacks.user.addToLog(params, null);
}
// No auto-notification, display what was going to be added.
if (type !== 'orphaned fair use') {
var noteData = document.createElement('pre');
noteData.appendChild(document.createTextNode('{{subst:Uploadvionotice|' + Morebits.pageNameNorm + '}}--~~~~'));
Morebits.status.info('提示', [conv({ hans: '这些内容应贴进上传者对话页:', hant: '這些內容應貼進上傳者討論頁:' }), document.createElement('br'), noteData]);
}
}
};
Twinkle.image.callbacks = {
taggingImage: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
// Adding discussion
if (params.type !== 'orphaned fair use') {
var wikipedia_page = new Morebits.wiki.page('Wikipedia:檔案存廢討論/快速刪除提報', conv({ hans: '加入快速删除记录项', hant: '加入快速刪除記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.image.callbacks.imageList);
}
var tag = '';
switch (params.type) {
case 'orphaned fair use':
tag = '{{subst:orphaned fair use}}\n';
break;
case 'no permission':
tag = '{{subst:' + params.templatename + '/auto|1=' + params.f8_source.replace(/http/g, 'http').replace(/\n+/g, '\n').replace(/^\s*([^*])/gm, '* $1').replace(/^\* $/m, '') + '}}\n';
break;
case 'replaceable fair use':
tag = '{{subst:' + params.templatename + '/auto|1=' + params.f10_type + '}}\n';
break;
default:
tag = '{{subst:' + params.templatename + '/auto}}\n';
break;
}
var textNoSd = text.replace(/\{\{\s*(db(-\w*)?|d|delete|(?:hang|hold)[- ]?on)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
if (text !== textNoSd && confirm(conv({ hans: '在页面上找到快速删除模板,要移除吗?', hant: '在頁面上找到快速刪除模板,要移除嗎?' }))) {
text = textNoSd;
}
pageobj.setPageText(tag + text);
var editSummary = conv({ hans: '请求快速删除(', hant: '請求快速刪除(' });
if (params.normalized === 'f3 f4') {
editSummary += '[[WP:CSD#F3|CSD F3]]+[[WP:CSD#F4|CSD F4]]';
} else {
editSummary += '[[WP:CSD#' + params.normalized.toUpperCase() + '|CSD ' + params.normalized.toUpperCase() + ']]';
}
editSummary += ')';
pageobj.setEditSummary(editSummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('deliWatchPage'));
pageobj.setCreateOption('nocreate');
pageobj.save();
},
userNotification: function(pageobj) {
var params = pageobj.getCallbackParameters();
var initialContrib = pageobj.getCreator();
// disallow warning yourself
if (initialContrib === mw.config.get('wgUserName')) {
pageobj.getStatusElement().warn('您(' + initialContrib + conv({ hans: ')创建了该页,跳过通知', hant: ')建立了該頁,跳過通知' }));
} else {
var talkPageName = 'User talk:' + initialContrib;
Morebits.wiki.flow.check(talkPageName, function () {
var flowpage = new Morebits.wiki.flow(talkPageName, conv({ hans: '通知上传者(', hant: '通知上傳者(' }) + initialContrib + ')');
flowpage.setTopic(conv({ hans: '文件[[', hant: '檔案[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的快速删除通知', hant: ']]的快速刪除通知' }));
flowpage.setContent('{{subst:Di-' + params.templatename + '-notice|1=' + Morebits.pageNameNorm + '}}');
flowpage.newTopic();
}, function () {
var usertalkpage = new Morebits.wiki.page(talkPageName, conv({ hans: '通知上传者(', hant: '通知上傳者(' }) + initialContrib + ')');
var notifytext = '\n{{subst:Di-' + params.templatename + '-notice|1=' + Morebits.pageNameNorm + '}}--~~~~';
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary(conv({ hans: '通知:文件[[', hant: '通知:檔案[[' }) + Morebits.pageNameNorm + conv({ hans: ']]快速删除提名', hant: ']]快速刪除提名' }));
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setWatchlist(Twinkle.getPref('deliWatchUser'));
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append();
});
}
// add this nomination to the user's userspace log, if the user has enabled it
if (params.lognomination) {
params.fromDI = true;
Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
}
},
imageList: function(pageobj) {
var text = pageobj.getPageText();
// var params = pageobj.getCallbackParameters();
pageobj.setPageText(text + '\n* [[:' + Morebits.pageNameNorm + ']]--~~~~');
pageobj.setEditSummary('加入[[' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.save();
}
};
Twinkle.addInitCallback(Twinkle.image, 'image');
})(jQuery);
// </nowiki>
7e0314e913de8c516941e1c946e4818e228f8a35
MediaWiki:Gadget-twinkleprotect.js
8
160
323
322
2024-08-03T04:07:25Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleprotect.js: Protect/RPP module
****************************************
* Mode of invocation: Tab ("PP"/"RPP")
* Active on: Non-special, non-MediaWiki pages
*/
// Note: a lot of code in this module is re-used/called by batchprotect.
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.protect = function twinkleprotect() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgNamespaceNumber') === 8) {
return;
}
// 如果是Flow讨论版而且是“Topic:”开头的帖子则不显示
if (mw.config.get('wgPageContentModel') === 'flow-board' && mw.config.get('wgPageName').indexOf('Topic:') === 0) {
return;
}
Twinkle.addPortletLink(Twinkle.protect.callback, conv({ hans: '保护', hant: '保護' }), 'tw-rpp',
Morebits.userIsSysop ? conv({ hans: '保护页面', hant: '保護頁面' }) : conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
};
Twinkle.protect.callback = function twinkleprotectCallback() {
var Window = new Morebits.simpleWindow(620, 530);
Window.setTitle(Morebits.userIsSysop ? conv({ hans: '施行或请求保护页面', hant: '施行或請求保護頁面' }) : conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '保护模板', hant: '保護模板' }), 'Template:Protection templates');
Window.addFooterLink(conv({ hans: '保护方针', hant: '保護方針' }), 'WP:PROT');
Window.addFooterLink(conv({ hans: '保护设置', hant: '保護設定' }), 'WP:TW/PREF#protect');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#protect');
var form = new Morebits.quickForm(Twinkle.protect.callback.evaluate);
var actionfield = form.append({
type: 'field',
label: conv({ hans: '操作类型', hant: '操作類別' })
});
if (Morebits.userIsSysop) {
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: conv({ hans: '保护页面', hant: '保護頁面' }),
value: 'protect',
checked: true
}
]
});
}
actionfield.append({
type: 'radio',
name: 'actiontype',
event: Twinkle.protect.callback.changeAction,
list: [
{
label: conv({ hans: '请求保护页面', hant: '請求保護頁面' }),
value: 'request',
tooltip: conv({ hans: '如果您想在WP:RFPP请求保护此页', hant: '如果您想在WP:RFPP請求保護此頁' }) + (Morebits.userIsSysop ? '而不是自行完成。' : '。'),
checked: !Morebits.userIsSysop
},
{
label: conv({ hans: '用保护模板标记此页', hant: '用保護模板標記此頁' }),
value: 'tag',
tooltip: conv({ hans: '可以用此为页面加上合适的保护模板。', hant: '可以用此為頁面加上合適的保護模板。' }),
disabled: mw.config.get('wgArticleId') === 0 || mw.config.get('wgPageContentModel') === 'Scribunto'
}
]
});
form.append({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
form.append({ type: 'field', label: '1', name: 'field1' });
form.append({ type: 'field', label: '2', name: 'field2' });
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// We must init the controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.actiontype[0].dispatchEvent(evt);
// get current protection level asynchronously
Twinkle.protect.fetchProtectionLevel();
};
// Customizable namespace and FlaggedRevs settings
// In theory it'd be nice to have restrictionlevels defined here,
// but those are only available via a siteinfo query
// Limit template editor; a Twinkle restriction, not a site setting
var isTemplate = mw.config.get('wgNamespaceNumber') === 10 || mw.config.get('wgNamespaceNumber') === 828;
// Contains the current protection level in an object
// Once filled, it will look something like:
// { edit: { level: "sysop", expiry: <some date>, cascade: true }, ... }
Twinkle.protect.currentProtectionLevels = {};
Twinkle.protect.previousProtectionLevels = {};
Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLevel() {
var api = new mw.Api();
var protectDeferred = api.get({
format: 'json',
indexpageids: true,
action: 'query',
list: 'logevents',
letype: 'protect',
letitle: mw.config.get('wgPageName'),
prop: 'info',
inprop: 'protection|watched',
titles: mw.config.get('wgPageName')
});
$.when.apply($, [protectDeferred]).done(function(protectData) {
var pageid = protectData.query.pageids[0];
var page = protectData.query.pages[pageid];
var current = {};
var previous = {};
// Save requested page's watched status for later in case needed when filing request
Twinkle.protect.watched = page.watchlistexpiry || page.watched === '';
$.each(page.protection, function(index, protection) {
if (protection.type !== 'aft') {
current[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
}
});
// Only use the log except unprotect
if (protectData.query.logevents.length >= 1 && protectData.query.logevents[0].action !== 'unprotect') {
Twinkle.protect.previousProtectionLog = protectData.query.logevents[0];
} else if (protectData.query.logevents.length >= 2) {
Twinkle.protect.previousProtectionLog = protectData.query.logevents[1];
}
if (Twinkle.protect.previousProtectionLog) {
$.each(Twinkle.protect.previousProtectionLog.params.details, function(index, protection) {
if (protection.type !== 'aft') {
previous[protection.type] = {
level: protection.level,
expiry: protection.expiry,
cascade: protection.cascade === ''
};
}
});
}
// show the protection level and log info
Twinkle.protect.hasProtectLog = !!protectData.query.logevents.length;
Twinkle.protect.currentProtectionLevels = current;
Twinkle.protect.previousProtectionLevels = previous;
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
});
};
Twinkle.protect.callback.showLogAndCurrentProtectInfo = function twinkleprotectCallbackShowLogAndCurrentProtectInfo() {
var currentlyProtected = !$.isEmptyObject(Twinkle.protect.currentProtectionLevels);
if (Twinkle.protect.hasProtectLog || Twinkle.protect.hasStableLog) {
var $linkMarkup = $('<span>');
if (Twinkle.protect.hasProtectLog) {
$linkMarkup.append(
$('<a target="_blank" href="' + mw.util.getUrl('Special:Log', { action: 'view', page: mw.config.get('wgPageName'), type: 'protect' }) + '">' + conv({ hans: '保护日志', hant: '保護日誌' }) + '</a>'),
Twinkle.protect.hasStableLog ? $('<span> • </span>') : null
);
}
Morebits.status.init($('div[name="hasprotectlog"] span')[0]);
Morebits.status.warn(
currentlyProtected
? conv({ hans: '先前保护', hant: '先前保護' })
: [
conv({ hans: '此页面曾在', hant: '此頁面曾在' }),
$('<b>' + new Morebits.date(Twinkle.protect.previousProtectionLog.timestamp).calendar('utc') + '</b>')[0],
'被' + Twinkle.protect.previousProtectionLog.user + conv({ hans: '保护', hant: '保護' }) + ':'
].concat(Twinkle.protect.formatProtectionDescription(Twinkle.protect.previousProtectionLevels)),
$linkMarkup[0]
);
}
Morebits.status.init($('div[name="currentprot"] span')[0]);
var protectionNode = [], statusLevel = 'info';
protectionNode = Twinkle.protect.formatProtectionDescription(Twinkle.protect.currentProtectionLevels);
if (currentlyProtected) {
statusLevel = 'warn';
}
Morebits.status[statusLevel](conv({ hans: '当前保护等级', hant: '目前保護等級' }), protectionNode);
};
Twinkle.protect.callback.changeAction = function twinkleprotectCallbackChangeAction(e) {
var field_preset;
var field1;
var field2;
switch (e.target.values) {
case 'protect':
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '默认', hant: '預設' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: conv({ hans: '选择默认:', hant: '選擇預設:' }),
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypesAdmin : Twinkle.protect.protectionTypesCreate
});
field2 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '保护选项', hant: '保護選項' }), name: 'field2' });
field2.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field2.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
// for existing pages
if (mw.config.get('wgArticleId')) {
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.editmodify,
list: [
{
label: conv({ hans: '修改编辑权限', hant: '修改編輯權限' }),
name: 'editmodify',
tooltip: conv({ hans: '如果此项关闭,编辑权限将不会修改。', hant: '如果此項關閉,編輯權限將不會修改。' }),
checked: true
}
]
});
field2.append({
type: 'select',
name: 'editlevel',
label: conv({ hans: '编辑权限:', hant: '編輯權限:' }),
event: Twinkle.protect.formevents.editlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE outside of templates and modules
return isTemplate || level.value !== 'templateeditor';
})
});
field2.append({
type: 'select',
name: 'editexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
$('input[name=small]', $(e.target).closest('form'))[0].checked = e.target.selectedIndex >= 4; // 1 month
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
field2.append({
type: 'checkbox',
event: Twinkle.protect.formevents.movemodify,
list: [
{
label: conv({ hans: '修改移动权限', hant: '修改移動權限' }),
name: 'movemodify',
tooltip: conv({ hans: '如果此项被关闭,移动权限将不被修改。', hant: '如果此項被關閉,移動權限將不被修改。' }),
checked: true
}
]
});
field2.append({
type: 'select',
name: 'movelevel',
label: conv({ hans: '移动权限:', hant: '移動權限:' }),
event: Twinkle.protect.formevents.movelevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Autoconfirmed is required for a move, redundant
return level.value !== 'autoconfirmed' && (isTemplate || level.value !== 'templateeditor');
})
});
field2.append({
type: 'select',
name: 'moveexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (2 days) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
} else { // for non-existing pages
field2.append({
type: 'select',
name: 'createlevel',
label: conv({ hans: '创建权限:', hant: '建立權限:' }),
event: Twinkle.protect.formevents.createlevel,
list: Twinkle.protect.protectionLevels.filter(function(level) {
// Filter TE always, and autoconfirmed in mainspace, redundant since WP:ACPERM
return level.value !== 'templateeditor';
})
});
field2.append({
type: 'select',
name: 'createexpiry',
label: conv({ hans: '终止时间:', hant: '終止時間:' }),
event: function(e) {
if (e.target.value === 'custom') {
Twinkle.protect.doCustomExpiry(e.target);
}
},
// default expiry selection (indefinite) is conditionally set in Twinkle.protect.callback.changePreset
list: Twinkle.protect.protectionLengths
});
}
field2.append({
type: 'checkbox',
list: [
{
name: 'close',
label: conv({ hans: '标记请求保护页面中的请求', hant: '標記請求保護頁面中的請求' }),
checked: true
}
]
});
field2.append({
type: 'textarea',
name: 'protectReason',
label: conv({ hans: '理由(保护日志):', hant: '理由(保護日誌):' })
});
if (!mw.config.get('wgArticleId') || mw.config.get('wgPageContentModel') === 'Scribunto') { // tagging isn't relevant for non-existing or module pages
break;
}
/* falls through */
case 'tag':
field1 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '标记选项', hant: '標記選項' }), name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'tagtype',
label: conv({ hans: '选择保护模板:', hant: '選擇保護模板:' }),
list: Twinkle.protect.protectionTags,
event: Twinkle.protect.formevents.tagtype
});
field1.append({
type: 'checkbox',
list: [
{
name: 'small',
label: conv({ hans: '使用图标(small=yes)', hant: '使用圖示(small=yes)' }),
tooltip: conv({ hans: '将给模板加上|small=yes参数,显示成右上角的一把挂锁。', hant: '將給模板加上|small=yes參數,顯示成右上角的一把掛鎖。' })
},
{
name: 'noinclude',
label: conv({ hans: '用<noinclude>包裹保护模板', hant: '用<noinclude>包裹保護模板' }),
tooltip: conv({ hans: '将保护模板包裹在<noinclude>中', hant: '將保護模板包裹在<noinclude>中' }),
checked: mw.config.get('wgNamespaceNumber') === 10
},
{
name: 'showexpiry',
label: conv({ hans: '在模板显示到期时间', hant: '在模板顯示到期時間' }),
tooltip: conv({ hans: '将给模板加上|expiry参数', hant: '將給模板加上|expiry參數' }),
checked: true,
hidden: e.target.values === 'tag'
}
]
});
break;
case 'request':
field_preset = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '保护类型', hant: '保護類別' }), name: 'field_preset' });
field_preset.append({
type: 'select',
name: 'category',
label: conv({ hans: '类型和理由:', hant: '類別和理由:' }),
event: Twinkle.protect.callback.changePreset,
list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate
});
field1 = new Morebits.quickForm.element({ type: 'field', label: conv({ hans: '选项', hant: '選項' }), name: 'field1' });
field1.append({ type: 'div', name: 'currentprot', label: ' ' }); // holds the current protection level, as filled out by the async callback
field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
field1.append({
type: 'select',
name: 'expiry',
label: conv({ hans: '时长:', hant: '時長:' }),
list: [
{ label: '', selected: true, value: '' },
{ label: conv({ hans: '临时', hant: '臨時' }), value: 'temporary' },
{ label: '永久', value: 'infinity' }
]
});
field1.append({
type: 'textarea',
name: 'reason',
label: '理由:'
});
break;
default:
alert(conv({ hans: '这玩意儿被逆袭的天邪鬼吃掉了!', hant: '這玩意兒被逆襲的天邪鬼吃掉了!' }));
break;
}
var oldfield;
if (field_preset) {
oldfield = $(e.target.form).find('fieldset[name="field_preset"]')[0];
oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field_preset"]').css('display', 'none');
}
if (field1) {
oldfield = $(e.target.form).find('fieldset[name="field1"]')[0];
oldfield.parentNode.replaceChild(field1.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field1"]').css('display', 'none');
}
if (field2) {
oldfield = $(e.target.form).find('fieldset[name="field2"]')[0];
oldfield.parentNode.replaceChild(field2.render(), oldfield);
} else {
$(e.target.form).find('fieldset[name="field2"]').css('display', 'none');
}
if (e.target.values === 'protect') {
// fake a change event on the preset dropdown
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
e.target.form.category.dispatchEvent(evt);
// reduce vertical height of dialog
$(e.target.form).find('fieldset[name="field2"] select').parent().css({ display: 'inline-block', marginRight: '0.5em' });
}
// re-add protection level and log info, if it's available
Twinkle.protect.callback.showLogAndCurrentProtectInfo();
};
// NOTE: This function is used by batchprotect as well
Twinkle.protect.formevents = {
editmodify: function twinkleprotectFormEditmodifyEvent(e) {
e.target.form.editlevel.disabled = !e.target.checked;
e.target.form.editexpiry.disabled = !e.target.checked || (e.target.form.editlevel.value === 'all');
e.target.form.editlevel.style.color = e.target.form.editexpiry.style.color = e.target.checked ? '' : 'transparent';
},
editlevel: function twinkleprotectFormEditlevelEvent(e) {
e.target.form.editexpiry.disabled = e.target.value === 'all';
},
movemodify: function twinkleprotectFormMovemodifyEvent(e) {
// sync move settings with edit settings if applicable
if (e.target.form.movelevel.disabled && !e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = e.target.form.editlevel.value;
e.target.form.moveexpiry.value = e.target.form.editexpiry.value;
} else if (e.target.form.editlevel.disabled) {
e.target.form.movelevel.value = 'sysop';
e.target.form.moveexpiry.value = 'infinity';
}
e.target.form.movelevel.disabled = !e.target.checked;
e.target.form.moveexpiry.disabled = !e.target.checked || (e.target.form.movelevel.value === 'all');
e.target.form.movelevel.style.color = e.target.form.moveexpiry.style.color = e.target.checked ? '' : 'transparent';
},
movelevel: function twinkleprotectFormMovelevelEvent(e) {
e.target.form.moveexpiry.disabled = e.target.value === 'all';
},
createlevel: function twinkleprotectFormCreatelevelEvent(e) {
e.target.form.createexpiry.disabled = e.target.value === 'all';
},
tagtype: function twinkleprotectFormTagtypeEvent(e) {
e.target.form.small.disabled = e.target.form.noinclude.disabled = e.target.form.showexpiry.disabled = (e.target.value === 'none') || (e.target.value === 'noop');
}
};
Twinkle.protect.doCustomExpiry = function twinkleprotectDoCustomExpiry(target) {
var custom = prompt(conv({ hans: '输入自定义终止时间。\n您可以使用相对时间,如“1 minute”或“19 days”,或绝对时间“yyyymmddhhmm”(如“200602011405”是2006年02月01日14:05(UTC))', hant: '輸入自訂終止時間。\n您可以使用相對時間,如「1 minute」或「19 days」,或絕對時間「yyyymmddhhmm」(如「200602011405」是2006年02月01日14:05(UTC))' }), '');
if (custom) {
var option = document.createElement('option');
option.setAttribute('value', custom);
option.textContent = custom;
target.appendChild(option);
target.value = custom;
} else {
target.selectedIndex = 0;
}
};
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLevels = [
{ label: '全部', value: 'all' },
{ label: conv({ hans: '仅允许自动确认用户', hant: '僅允許自動確認使用者' }), value: 'autoconfirmed' },
{ label: conv({ hans: '仅允许延伸确认用户', hant: '僅允許延伸確認使用者' }), value: 'extendedconfirmed' },
{ label: conv({ hans: '仅模板编辑员和管理员', hant: '僅模板編輯員和管理員' }), value: 'templateeditor' },
{ label: conv({ hans: '仅管理员', hant: '僅管理員' }), value: 'sysop', selected: true }
];
// default expiry selection is conditionally set in Twinkle.protect.callback.changePreset
// NOTE: This list is used by batchprotect as well
Twinkle.protect.protectionLengths = [
{ label: '1天', value: '1 day' },
{ label: '3天', value: '3 days' },
{ label: conv({ hans: '1周', hant: '1週' }), value: '1 week' },
{ label: conv({ hans: '2周', hant: '2週' }), value: '2 weeks' },
{ label: conv({ hans: '1个月', hant: '1個月' }), value: '1 month' },
{ label: conv({ hans: '3个月', hant: '3個月' }), value: '3 months' },
{ label: conv({ hans: '6个月', hant: '6個月' }), value: '6 months' },
{ label: '1年', value: '1 year' },
{ label: conv({ hans: '无限期', hant: '無限期' }), value: 'infinity' },
{ label: conv({ hans: '自定义…', hant: '自訂…' }), value: 'custom' }
];
Twinkle.protect.protectionTypesAdmin = [
{ label: conv({ hans: '解除保护', hant: '解除保護' }), value: 'unprotect' },
{
label: conv({ hans: '全保护', hant: '全保護' }),
list: [
{ label: conv({ hans: '常规(全)', hant: '常規(全)' }), value: 'pp-protected' },
{ label: conv({ hans: '争议、编辑战(全)', hant: '爭議、編輯戰(全)' }), value: 'pp-dispute' }
]
},
{
label: conv({ hans: '模板保护', hant: '模板保護' }),
list: [
{ label: conv({ hans: '高风险模板(模板)', hant: '高風險模板(模板)' }), value: 'pp-template' }
]
},
{
label: conv({ hans: '延伸确认保护', hant: '延伸確認保護' }),
list: [
{ label: conv({ hans: '争议、编辑战(延伸)', hant: '爭議、編輯戰(延伸)' }), value: 'pp-extend-dispute' },
{ label: conv({ hans: '持续破坏(延伸)', hant: '持續破壞(延伸)' }), value: 'pp-vandalism' },
{ label: conv({ hans: '傀儡破坏(延伸)', hant: '傀儡破壞(延伸)' }), value: 'pp-sock' }
]
},
{
label: conv({ hans: '半保护', hant: '半保護' }),
list: [
{ label: conv({ hans: '常规(半)', hant: '常規(半)' }), value: 'pp-semi-protected' },
{ label: conv({ hans: '持续破坏(半)', hant: '持續破壞(半)' }), value: 'pp-semi-vandalism' },
{ label: conv({ hans: '违反生者传记方针(半)', hant: '違反生者傳記方針(半)' }), value: 'pp-semi-blp' },
{ label: conv({ hans: '傀儡破坏(半)', hant: '傀儡破壞(半)' }), value: 'pp-semi-sock' },
{ label: conv({ hans: '高风险模板(半)', hant: '高風險模板(半)' }), value: 'pp-semi-template' },
{ label: conv({ hans: '被封禁用户滥用讨论页(半)', hant: '被封禁使用者濫用討論頁(半)' }), value: 'pp-semi-usertalk' }
]
},
{
label: conv({ hans: '移动保护', hant: '移動保護' }),
list: [
{ label: conv({ hans: '常规(移动)', hant: '常規(移動)' }), value: 'pp-move' },
{ label: conv({ hans: '争议、移动战(移动)', hant: '爭議、移動戰(移動)' }), value: 'pp-move-dispute' },
{ label: conv({ hans: '移动破坏(移动)', hant: '移動破壞(移動)' }), value: 'pp-move-vandalism' },
{ label: conv({ hans: '高风险页面(移动)', hant: '高風險頁面(移動)' }), value: 'pp-move-indef' }
]
}
].filter(function(type) {
// Filter for templates
return isTemplate || (type.label !== '模板保护' && type.label !== '模板保護');
});
Twinkle.protect.protectionTypesCreateOnly = [
{
label: conv({ hans: '白纸保护', hant: '白紙保護' }),
list: [
{ label: conv({ hans: '常规(白纸)', hant: '常規(白紙)' }), value: 'pp-create' },
{ label: conv({ hans: '多次重复创建(白纸)', hant: '多次重複建立(白紙)' }), value: 'pp-create-repeat' },
{ label: conv({ hans: '持续破坏(白纸)', hant: '持續破壞(白紙)' }), value: 'pp-create-vandalism' },
{ label: conv({ hans: '已封禁用户的用户页(白纸)', hant: '已封禁使用者的使用者頁(白紙)' }), value: 'pp-create-userpage' }
]
}
];
Twinkle.protect.protectionTypes = Twinkle.protect.protectionTypesAdmin.concat(
Twinkle.protect.protectionTypesCreateOnly);
Twinkle.protect.protectionTypesCreate = [
{ label: conv({ hans: '解除保护', hant: '解除保護' }), value: 'unprotect' }
].concat(Twinkle.protect.protectionTypesCreateOnly);
// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
// Also note: stabilize = Pending Changes level
// expiry will override any defaults
Twinkle.protect.protectionPresetsInfo = {
'pp-protected': {
edit: 'sysop',
move: 'sysop',
reason: null
},
'pp-dispute': {
edit: 'sysop',
move: 'sysop',
reason: conv({ hans: '编辑战', hant: '編輯戰' })
},
'pp-template': {
edit: 'templateeditor',
move: 'templateeditor',
expiry: 'infinity',
reason: conv({ hans: '[[WP:HRT|高风险模板]]', hant: '[[WP:HRT|高風險模板]]' }),
template: 'noop'
},
'pp-vandalism': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '被自动确认用户破坏', hant: '被自動確認使用者破壞' })
},
'pp-extend-dispute': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '自动确认用户编辑战', hant: '自動確認使用者編輯戰' }),
template: 'pp-dispute'
},
'pp-sock': {
edit: 'extendedconfirmed',
move: 'extendedconfirmed',
reason: conv({ hans: '持续的傀儡破坏', hant: '持續的傀儡破壞' })
},
'pp-semi-vandalism': {
edit: 'autoconfirmed',
reason: conv({ hans: '被IP用户或新用户破坏', hant: '被IP使用者或新使用者破壞' }),
template: 'pp-vandalism'
},
'pp-semi-blp': {
edit: 'autoconfirmed',
reason: conv({ hans: 'IP用户或新用户违反生者传记方针', hant: 'IP使用者或新使用者違反生者傳記方針' })
},
'pp-semi-usertalk': {
edit: 'autoconfirmed',
reason: conv({ hans: '被封禁用户滥用其讨论页', hant: '被封禁使用者濫用其討論頁' })
},
'pp-semi-template': { // removed for now
edit: 'autoconfirmed',
expiry: 'infinity',
reason: conv({ hans: '[[WP:HRT|高风险模板]]', hant: '[[WP:HRT|高風險模板]]' }),
template: 'noop'
},
'pp-semi-sock': {
edit: 'autoconfirmed',
reason: conv({ hans: '持续的傀儡破坏', hant: '持續的傀儡破壞' }),
template: 'pp-sock'
},
'pp-semi-protected': {
edit: 'autoconfirmed',
reason: null,
template: 'pp-protected'
},
'pp-move': {
move: 'sysop',
reason: null
},
'pp-move-dispute': {
move: 'sysop',
reason: conv({ hans: '页面移动战', hant: '頁面移動戰' })
},
'pp-move-vandalism': {
move: 'sysop',
reason: conv({ hans: '移动破坏', hant: '移動破壞' })
},
'pp-move-indef': {
move: 'sysop',
expiry: 'infinity',
reason: conv({ hans: '高风险页面', hant: '高風險頁面' })
},
'unprotect': {
edit: 'all',
move: 'all',
create: 'all',
reason: null,
template: 'none'
},
'pp-create': {
create: 'autoconfirmed',
reason: null
},
'pp-create-repeat': {
create: 'autoconfirmed',
reason: conv({ hans: '多次重复创建', hant: '多次重複建立' })
},
'pp-create-vandalism': {
create: 'autoconfirmed',
reason: conv({ hans: '被IP用户或新用户破坏', hant: '被IP使用者或新使用者破壞' })
},
'pp-create-userpage': {
create: 'sysop',
expiry: 'infinity',
reason: conv({ hans: '被永久封禁的用户页', hant: '被永久封禁的使用者頁面' })
}
};
Twinkle.protect.protectionTags = [
{
label: conv({ hans: '无(移除现有模板)', hant: '無(移除現有模板)' }),
value: 'none'
},
{
label: conv({ hans: '无(不移除现有模板)', hant: '無(不移除現有模板)' }),
value: 'noop'
},
{
label: '通用模板',
list: [
{ label: '{{pp-dispute}}: ' + conv({ hans: '争议', hant: '爭議' }), value: 'pp-dispute' },
{ label: '{{pp-vandalism}}: ' + conv({ hans: '破坏', hant: '破壞' }), value: 'pp-vandalism', selected: true },
{ label: '{{pp-sock}}: ' + '傀儡', value: 'pp-sock' },
{ label: '{{pp-template}}: ' + conv({ hans: '高风险模板', hant: '高風險模板' }), value: 'pp-template' },
{ label: '{{pp-protected}}: ' + conv({ hans: '常规', hant: '常規' }), value: 'pp-protected' }
]
},
{
label: conv({ hans: '半保护模板', hant: '半保護模板' }),
list: [
{ label: '{{pp-semi-usertalk}}: ' + conv({ hans: '封禁的用户', hant: '封禁的使用者' }), value: 'pp-semi-usertalk' },
{ label: '{{pp-semi-blp}}: ' + conv({ hans: '生者传记', hant: '生者傳記' }), value: 'pp-semi-blp' },
{ label: '{{pp-semi-indef}}: ' + conv({ hans: '长期', hant: '長期' }), value: 'pp-semi-indef' }
]
},
{
label: conv({ hans: '移动保护模板', hant: '移動保護模板' }),
list: [
{ label: '{{pp-move-dispute}}: ' + conv({ hans: '争议', hant: '爭議' }), value: 'pp-move-dispute' },
{ label: '{{pp-move-vandalism}}: ' + conv({ hans: '破坏', hant: '破壞' }), value: 'pp-move-vandalism' },
{ label: '{{pp-move-indef}}: ' + conv({ hans: '长期', hant: '長期' }), value: 'pp-move-indef' },
{ label: '{{pp-move}}: ' + conv({ hans: '常规', hant: '常規' }), value: 'pp-move' }
]
}
];
Twinkle.protect.callback.changePreset = function twinkleprotectCallbackChangePreset(e) {
var form = e.target.form;
var actiontypes = form.actiontype;
var actiontype;
for (var i = 0; i < actiontypes.length; i++) {
if (!actiontypes[i].checked) {
continue;
}
actiontype = actiontypes[i].values;
break;
}
if (actiontype === 'protect') { // actually protecting the page
var item = Twinkle.protect.protectionPresetsInfo[form.category.value];
if (mw.config.get('wgArticleId')) {
if (item.edit) {
form.editmodify.checked = true;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
form.editlevel.value = item.edit;
Twinkle.protect.formevents.editlevel({ target: form.editlevel });
} else {
form.editmodify.checked = false;
Twinkle.protect.formevents.editmodify({ target: form.editmodify });
}
if (item.move) {
form.movemodify.checked = true;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
form.movelevel.value = item.move;
Twinkle.protect.formevents.movelevel({ target: form.movelevel });
} else {
form.movemodify.checked = false;
Twinkle.protect.formevents.movemodify({ target: form.movemodify });
}
form.editexpiry.value = form.moveexpiry.value = item.expiry || '1 week';
} else {
if (item.create) {
form.createlevel.value = item.create;
Twinkle.protect.formevents.createlevel({ target: form.createlevel });
form.createexpiry.value = item.createexpiry || '1 week';
}
form.createexpiry.value = item.expiry || '1 week';
}
var reasonField = actiontype === 'protect' ? form.protectReason : form.reason;
if (item.reason) {
reasonField.value = item.reason;
} else {
reasonField.value = '';
}
// sort out tagging options, disabled if nonexistent or lua
if (mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto') {
if (form.category.value === 'unprotect') {
form.tagtype.value = 'none';
} else {
form.tagtype.value = item.template ? item.template : form.category.value;
}
Twinkle.protect.formevents.tagtype({ target: form.tagtype });
if (/template/.test(form.category.value)) {
form.noinclude.checked = true;
} else if (mw.config.get('wgNamespaceNumber') !== 10) {
form.noinclude.checked = false;
}
}
} else { // RPP request
if (form.category.value === 'unprotect') {
form.expiry.value = '';
form.expiry.disabled = true;
} else {
form.expiry.value = '';
form.expiry.disabled = false;
}
}
};
Twinkle.protect.callback.evaluate = function twinkleprotectCallbackEvaluate(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
var tagparams;
if (input.actiontype === 'tag' || (input.actiontype === 'protect' && mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto')) {
tagparams = {
tag: input.tagtype,
reason: (input.tagtype === 'pp-protected' || input.tagtype === 'pp-semi-protected' || input.tagtype === 'pp-move') && input.protectReason ? input.protectReason : null,
showexpiry: input.actiontype === 'protect' ? input.showexpiry : null,
small: input.small,
noinclude: input.noinclude
};
if (input.actiontype === 'protect') {
if (input.editmodify) {
tagparams.expiry = input.editexpiry;
} else if (input.movemodify) {
tagparams.expiry = input.moveexpiry;
}
}
}
var closeparams = {};
if (input.close) {
if (input.category === 'unprotect') {
closeparams.type = 'unprotect';
} else if (mw.config.get('wgArticleId')) {
if (input.editmodify) {
if (input.editlevel === 'sysop') {
closeparams.type = 'full';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'templateeditor') {
closeparams.type = 'temp';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'extendedconfirmed') {
closeparams.type = 'ecp';
closeparams.expiry = input.editexpiry;
} else if (input.editlevel === 'autoconfirmed') {
closeparams.type = 'semi';
closeparams.expiry = input.editexpiry;
}
} else if (input.movemodify && ['sysop', 'templateeditor', 'extendedconfirmed'].indexOf(input.movelevel) !== -1) {
closeparams.type = 'move';
closeparams.expiry = input.moveexpiry;
}
} else {
if (input.createlevel !== 'all') {
closeparams.type = 'salt';
closeparams.expiry = input.createexpiry;
}
}
}
switch (input.actiontype) {
case 'protect':
// protect the page
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '保护完成', hant: '保護完成' });
var statusInited = false;
var thispage;
var allDone = function twinkleprotectCallbackAllDone() {
if (thispage) {
thispage.getStatusElement().info('完成');
}
if (tagparams) {
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
}
if (closeparams && closeparams.type) {
var rppPage = new Morebits.wiki.page('Wikipedia:请求保护页面', conv({ hans: '关闭请求', hant: '關閉請求' }));
rppPage.setFollowRedirect(true);
rppPage.setCallbackParameters(closeparams);
rppPage.load(Twinkle.protect.callbacks.closeRequest);
}
};
var protectIt = function twinkleprotectCallbackProtectIt(next) {
thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '保护页面', hant: '保護頁面' }));
var anyExtendProtection = false;
if (mw.config.get('wgArticleId')) {
if (input.editmodify) {
if (input.editlevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setEditProtection(input.editlevel, input.editexpiry);
}
if (input.movemodify) {
// Ensure a level has actually been chosen
if (input.movelevel) {
if (input.movelevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setMoveProtection(input.movelevel, input.moveexpiry);
} else {
alert(conv({ hans: '您需要选择保护层级!', hant: '您需要選擇保護層級!' }));
return;
}
}
thispage.setWatchlist(Twinkle.getPref('watchProtectedPages'));
} else {
if (input.createlevel === 'extendedconfirmed') {
anyExtendProtection = true;
}
thispage.setCreateProtection(input.createlevel, input.createexpiry);
thispage.setWatchlist(false);
}
if (input.protectReason) {
if (anyExtendProtection && !/(争议|爭議|编辑战|編輯戰|破坏|破壞|重复创建|重複建立)/.test(input.protectReason)
&& !confirm(conv({ hans: '根据保护方针,延伸确认保护仅可用于编辑战或破坏,但是您指定的保护理由似乎未符此条件。单击确认以继续保护,单击取消以更改保护设置', hant: '根據保護方針,延伸確認保護僅可用於編輯戰或破壞,但是您指定的保護理由似乎未符此條件。點擊確認以繼續保護,點擊取消以更改保護設定' }))) {
return;
}
thispage.setEditSummary(input.protectReason);
thispage.setChangeTags(Twinkle.changeTags);
} else {
alert(conv({ hans: '您必须输入保护理由,这将被记录在保护日志中。', hant: '您必須輸入保護理由,這將被記錄在保護日誌中。' }));
return;
}
if (!statusInited) {
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
statusInited = true;
}
thispage.setChangeTags(Twinkle.changeTags);
thispage.protect(next);
};
if (input.editmodify || input.movemodify || !mw.config.get('wgArticleId')) {
protectIt(allDone);
} else {
alert(conv({ hans: '请告诉Twinkle要做什么!\n如果您只是想标记该页,请选择上面的“用保护模板标记此页”选项。', hant: '請告訴Twinkle要做什麼!\n如果您只是想標記該頁,請選擇上面的「用保護模板標記此頁」選項。' }));
}
break;
case 'tag':
// apply a protection template
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.followRedirect = false;
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成', hant: '標記完成' });
Twinkle.protect.callbacks.taggingPageInitial(tagparams);
break;
case 'request':
// file request at RFPP
var typename, typereason;
switch (input.category) {
case 'pp-dispute':
case 'pp-protected':
typename = conv({ hans: '全保护', hant: '全保護' });
break;
case 'pp-template':
typename = conv({ hans: '模板保护', hant: '模板保護' });
break;
case 'pp-vandalism':
case 'pp-extend-dispute':
typename = conv({ hans: '延伸确认保护', hant: '延伸確認保護' });
break;
case 'pp-semi-vandalism':
case 'pp-semi-usertalk':
case 'pp-semi-template': // removed for now
case 'pp-semi-sock':
case 'pp-semi-blp':
case 'pp-semi-protected':
typename = conv({ hans: '半保护', hant: '半保護' });
break;
case 'pp-move':
case 'pp-move-dispute':
case 'pp-move-indef':
case 'pp-move-vandalism':
typename = conv({ hans: '移动保护', hant: '移動保護' });
break;
case 'pp-create':
case 'pp-create-offensive':
case 'pp-create-blp':
case 'pp-create-salt':
case 'pp-create-userpage':
case 'pp-create-repeat':
case 'pp-create-vandalism':
typename = conv({ hans: '白纸保护', hant: '白紙保護' });
break;
case 'unprotect':
/* falls through */
default:
typename = conv({ hans: '解除保护', hant: '解除保護' });
break;
}
switch (input.category) {
case 'pp-dispute':
case 'pp-extend-dispute':
typereason = conv({ hans: '争议、编辑战', hant: '爭議、編輯戰' });
break;
case 'pp-vandalism':
case 'pp-semi-vandalism':
case 'pp-create-vandalism':
typereason = conv({ hans: '持续破坏', hant: '持續破壞' });
break;
case 'pp-template':
case 'pp-semi-template': // removed for now
typereason = conv({ hans: '高风险模板', hant: '高風險模板' });
break;
case 'pp-create-userpage':
typereason = conv({ hans: '被永久封禁的用户页', hant: '被永久封鎖的使用者頁面' });
break;
case 'pp-semi-usertalk':
typereason = conv({ hans: '已封禁用户的讨论页', hant: '已封鎖使用者的討論頁' });
break;
case 'pp-semi-sock':
typereason = conv({ hans: '傀儡破坏', hant: '傀儡破壞' });
break;
case 'pp-semi-blp':
typereason = conv({ hans: '违反生者传记方针', hant: '違反生者傳記方針' });
break;
case 'pp-move-dispute':
typereason = conv({ hans: '争议、移动战', hant: '爭議、移動戰' });
break;
case 'pp-move-vandalism':
typereason = conv({ hans: '移动破坏', hant: '移動破壞' });
break;
case 'pp-move-indef':
typereason = conv({ hans: '高风险页面', hant: '高風險頁面' });
break;
case 'pp-create-repeat':
typereason = conv({ hans: '多次重复创建', hant: '多次重複建立' });
break;
default:
typereason = '';
break;
}
var reason = typereason;
if (input.reason !== '') {
if (typereason !== '') {
reason += ':';
}
reason += input.reason;
}
if (reason !== '') {
reason = Morebits.string.appendPunctuation(reason);
}
var rppparams = {
reason: reason,
typename: typename,
category: input.category,
expiry: input.expiry
};
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var rppName = 'Wikipedia:请求保护页面';
// Updating data for the action completed event
Morebits.wiki.actionCompleted.redirect = rppName;
Morebits.wiki.actionCompleted.notice = conv({ hans: '提名完成,重定向到讨论页', hant: '提名完成,重新導向到討論頁' });
var rppPage = new Morebits.wiki.page(rppName, conv({ hans: '请求保护页面', hant: '請求保護頁面' }));
rppPage.setFollowRedirect(true);
rppPage.setCallbackParameters(rppparams);
rppPage.load(Twinkle.protect.callbacks.fileRequest);
break;
default:
alert('twinkleprotect: 未知操作类型');
break;
}
};
Twinkle.protect.callbacks = {
taggingPageInitial: function(tagparams) {
if (tagparams.tag === 'noop') {
Morebits.status.info(conv({ hans: '应用保护模板', hant: '應用保護模板' }), conv({ hans: '没什么要做的', hant: '沒什麼要做的' }));
return;
}
var pageName = mw.config.get('wgPageName');
Morebits.wiki.flow.check(pageName, function () {
var flowpage = new Morebits.wiki.flow(pageName, conv({ hans: '标记Flow页描述', hant: '標記Flow頁描述' }));
flowpage.setCallbackParameters(tagparams);
flowpage.viewHeader(Twinkle.protect.callbacks.taggingFlowPage);
}, function () {
var protectedPage = new Morebits.wiki.page(pageName, conv({ hans: '标记页面', hant: '標記頁面' }));
protectedPage.setCallbackParameters(tagparams);
protectedPage.load(Twinkle.protect.callbacks.taggingPage);
});
},
getTaggedPage: function(params, text) {
var tag, summary;
var oldtag_re = /(?:<noinclude>)?[ \t]*\{\{\s*(pp-[^{}]*?|protected|(?:t|v|s|p-|usertalk-v|usertalk-s|sb|move)protected(?:2)?|protected template|privacy protection)\s*?\}\}\s*(?:<\/noinclude>)?\s*/gi;
var re_result = oldtag_re.exec(text);
if (re_result) {
if (params.tag === 'none' || confirm(conv({ hans: '在页面上找到{{', hant: '在頁面上找到{{' }) + re_result[1] + conv({ hans: '}}\n单击确定以移除,或单击取消以取消操作。', hant: '}}\n點擊確定以移除,或點擊取消以取消操作。' }))) {
text = text.replace(oldtag_re, '');
}
}
if (params.tag === 'none') {
summary = conv({ hans: '移除保护模板', hant: '移除保護模板' });
} else {
tag = params.tag;
if (params.reason) {
tag += '|reason=' + params.reason;
}
if (params.showexpiry && params.expiry && !Morebits.string.isInfinity(params.expiry)) {
tag += '|expiry={{subst:#time:c|' + params.expiry + '}}';
}
if (params.small) {
tag += '|small=yes';
}
if (/^\s*#(?:redirect|重定向|重新導向)/i.test(text)) { // redirect page
// Only tag if no {{rcat shell}} is found
if (!text.match(/{{(?:Redirect[ _]category shell|Rcat[ _]shell|This[ _]is a redirect|多种类型重定向|多種類型重定向|多種類型重新導向|多种类型重新导向|R0|其他重定向|RCS|Redirect[ _]shell)/i)) {
text = text.replace(/#(?:redirect|重定向|重新導向) ?(\[\[.*?\]\])(.*)/i, '#REDIRECT $1$2\n\n{{' + tag + '}}');
} else {
Morebits.status.info('已存在Redirect category shell', conv({ hans: '没什么可做的', hant: '沒什麼可做的' }));
return;
}
} else {
if (params.noinclude) {
tag = '<noinclude>{{' + tag + '}}</noinclude>';
// 只有表格需要单独加回车,其他情况加回车会破坏模板。
if (text.indexOf('{|') === 0) {
tag += '\n';
}
} else {
tag = '{{' + tag + '}}\n';
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
summary = '加入{{' + params.tag + '}}';
}
return {
text: text,
summary: summary
};
},
taggingPage: function(protectedPage) {
var params = protectedPage.getCallbackParameters();
var text = protectedPage.getPageText();
var newVersion = Twinkle.protect.callbacks.getTaggedPage(params, text);
if (typeof newVersion === 'undefined') {
protectedPage.getStatusElement().info('完成');
return;
}
protectedPage.setEditSummary(newVersion.summary);
protectedPage.setChangeTags(Twinkle.changeTags);
protectedPage.setWatchlist(Twinkle.getPref('watchPPTaggedPages'));
protectedPage.setPageText(newVersion.text);
protectedPage.setCreateOption('nocreate');
protectedPage.suppressProtectWarning(); // no need to let admins know they are editing through protection
protectedPage.save();
},
taggingFlowPage: function(flowpage) {
var params = flowpage.getCallbackParameters();
var text = flowpage.getHeader();
var newVersion = Twinkle.protect.callbacks.getTaggedPage(params, text);
if (typeof newVersion === 'undefined') {
flowpage.getStatusElement().info('完成');
return;
}
flowpage.setHeader(newVersion.text);
flowpage.editHeader();
},
fileRequest: function(rppPage) {
var params = rppPage.getCallbackParameters();
var text = rppPage.getPageText();
var statusElement = rppPage.getStatusElement();
var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + Morebits.string.escapeRegExp(Morebits.pageNameNorm) + '\\s*(\\]\\])?\\s*===', 'm');
var tag = rppRe.exec(text);
var rppLink = document.createElement('a');
rppLink.setAttribute('href', mw.util.getUrl(rppPage.getPageName()));
rppLink.appendChild(document.createTextNode(rppPage.getPageName()));
if (tag) {
statusElement.error([rppLink, conv({ hans: '已有对此页面的保护提名,取消操作。', hant: '已有對此頁面的保護提名,取消操作。' })]);
return;
}
var newtag = '=== [[:' + Morebits.pageNameNorm + ']] ===' + '\n';
if (new RegExp('^' + mw.util.escapeRegExp(newtag).replace(/\s+/g, '\\s*'), 'm').test(text)) {
statusElement.error([rppLink, conv({ hans: '已有对此页面的保护提名,取消操作。', hant: '已有對此頁面的保護提名,取消操作。' })]);
return;
}
var words;
switch (params.expiry) {
case 'temporary':
words = conv({ hans: '临时', hant: '臨時' });
break;
case 'infinity':
words = '永久';
break;
default:
words = '';
break;
}
words += params.typename;
newtag += '* <small>' + conv({ hans: '当前保护状态', hant: '目前保護狀態' }) + ':{{protection status|' + (/=/.test(Morebits.pageNameNorm) ? '1=' : '') + Morebits.pageNameNorm + '}}</small>\n';
newtag += conv({ hans: '请求', hant: '請求' }) + Morebits.string.toUpperCaseFirstChar(words) + (params.reason !== '' ? ':' +
Morebits.string.formatReasonText(params.reason) : '。') + '--~~~~';
var reg;
if (params.category === 'unprotect') {
reg = /(==\s*请求解除保护\s*==)/;
} else {
reg = /({{\s*\/header\s*}})/;
}
var originalTextLength = text.length;
text = text.replace(reg, '$1\n' + newtag + '\n');
if (text.length === originalTextLength) {
var linknode = document.createElement('a');
linknode.setAttribute('href', mw.util.getUrl('Wikipedia:Twinkle/修复RFPP'));
linknode.appendChild(document.createTextNode(conv({ hans: '如何修复RFPP', hant: '如何修復RFPP' })));
statusElement.error([conv({ hans: '无法在WP:RFPP上找到相关定位点标记,要修复此问题,请参见', hant: '無法在WP:RFPP上找到相關定位點標記,要修復此問題,請參見' }), linknode, '。']);
return;
}
statusElement.status('加入新提名…');
rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ ' + conv({ hans: '请求对', hant: '請求對' }) + '[[' + Morebits.pageNameNorm + ']]' + params.typename);
rppPage.setChangeTags(Twinkle.changeTags);
rppPage.setPageText(text);
rppPage.setCreateOption('recreate');
rppPage.save(function() {
// Watch the page being requested
var watchPref = Twinkle.getPref('watchRequestedPages');
// action=watch has no way to rely on user preferences (T262912), so we do it manually.
// The watchdefault pref appears to reliably return '1' (string),
// but that's not consistent among prefs so might as well be "correct"
var watch = watchPref !== 'no' && (watchPref !== 'default' || !!parseInt(mw.user.options.get('watchdefault'), 10));
if (watch) {
var watch_query = {
action: 'watch',
titles: mw.config.get('wgPageName'),
token: mw.user.tokens.get('watchToken')
};
// Only add the expiry if page is unwatched or already temporarily watched
if (Twinkle.protect.watched !== true && watchPref !== 'default' && watchPref !== 'yes') {
watch_query.expiry = watchPref;
}
new Morebits.wiki.api(conv({ hans: '将请求保护的页面加入到监视列表', hant: '將請求保護的頁面加入到監視清單' }), watch_query).post();
}
});
},
closeRequest: function(rppPage) {
var params = rppPage.getCallbackParameters();
var text = rppPage.getPageText();
var statusElement = rppPage.getStatusElement();
var sections = text.split(/(?=\n==\s*请求解除保护\s*==)/);
if (sections.length !== 2) {
var linknode2 = document.createElement('a');
linknode2.setAttribute('href', mw.util.getUrl('Wikipedia:Twinkle/修复RFPP'));
linknode2.appendChild(document.createTextNode('如何修复RFPP'));
statusElement.error([conv({ hans: '无法在WP:RFPP上找到相关定位点标记,要修复此问题,请参见', hant: '無法在WP:RFPP上找到相關定位點標記,要修復此問題,請參見' }), linknode2, '。']);
return;
}
var sectionText, expiryText = '';
if (params.type === 'unprotect') {
sectionText = sections[1];
} else {
sectionText = sections[0];
expiryText = Morebits.string.formatTime(params.expiry);
}
var requestList = sectionText.split(/(?=\n===.+===\s*\n)/);
var found = false;
var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + Morebits.pageNameRegex(Morebits.pageNameNorm) + '\\s*(\\]\\])?\\s*===', 'm');
for (var i = 1; i < requestList.length; i++) {
if (rppRe.exec(requestList[i])) {
requestList[i] = requestList[i].trimRight();
if (params.type === 'unprotect') {
requestList[i] += '\n: {{RFPP|isun}}。--~~~~\n';
} else {
requestList[i] += '\n: {{RFPP|' + params.type + '|'
+ (Morebits.string.isInfinity(params.expiry) ? 'infinity' : expiryText)
+ '}}。--~~~~\n';
}
found = true;
break;
}
}
if (!found) {
statusElement.warn(conv({ hans: '没有找到相关的请求', hant: '沒有找到相關的請求' }));
return;
}
if (params.type === 'unprotect') {
text = sections[0] + requestList.join('');
} else {
text = requestList.join('') + sections[1];
}
var summary = '';
if (params.type === 'unprotect') {
sectionText = sections[1];
} else {
sectionText = sections[0];
}
switch (params.type) {
case 'semi':
summary = conv({ hans: '半保护', hant: '半保護' });
break;
case 'temp':
summary = conv({ hans: '模板保护', hant: '模板保護' });
break;
case 'ecp':
summary = conv({ hans: '延伸确认保护', hant: '延伸確認保護' });
break;
case 'full':
summary = conv({ hans: '全保护', hant: '全保護' });
break;
case 'move':
summary = conv({ hans: '移动保护', hant: '移動保護' });
break;
case 'salt':
summary = conv({ hans: '白纸保护', hant: '白紙保護' });
break;
case 'unprotect':
summary = conv({ hans: '解除保护', hant: '解除保護' });
break;
default:
statusElement.warn(conv({ hans: '未知保护类型', hant: '未知保護類別' }));
return;
}
if (Morebits.string.isInfinity(params.expiry)) {
summary = expiryText + summary;
} else {
summary += expiryText;
}
rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ ' + summary);
rppPage.setChangeTags(Twinkle.changeTags);
rppPage.setPageText(text);
rppPage.save();
}
};
Twinkle.protect.formatProtectionDescription = function(protectionLevels) {
var protectionNode = [];
if (!$.isEmptyObject(protectionLevels)) {
$.each(protectionLevels, function(type, settings) {
var label;
switch (type) {
case 'edit':
label = conv({ hans: '编辑', hant: '編輯' });
break;
case 'move':
label = conv({ hans: '移动', hant: '移動' });
break;
case 'create':
label = conv({ hans: '创建', hant: '建立' });
break;
case 'upload':
label = conv({ hans: '上传', hant: '上傳' });
break;
default:
label = type;
break;
}
var level;
switch (settings.level) {
case 'autoconfirmed':
level = conv({ hans: '仅允许自动确认用户', hant: '僅允許自動確認使用者' });
break;
case 'extendedconfirmed':
level = conv({ hans: '仅允许延伸确认用户', hant: '僅允許延伸確認使用者' });
break;
case 'templateeditor':
level = conv({ hans: '仅模板编辑员和管理员', hant: '僅模板編輯員和管理員' });
break;
case 'sysop':
level = conv({ hans: '仅管理员', hant: '僅管理員' });
break;
default:
level = settings.level;
break;
}
protectionNode.push($('<b>' + label + ':' + level + '</b>')[0]);
if (Morebits.string.isInfinity(settings.expiry)) {
protectionNode.push(conv({ hans: '(无限期)', hant: '(無限期)' }));
} else {
protectionNode.push(conv({ hans: '(过期:', hant: '(過期:' }) + new Morebits.date(settings.expiry).calendar('utc') + ')');
}
if (settings.cascade) {
protectionNode.push(conv({ hans: '(连锁)', hant: '(連鎖)' }));
}
});
} else {
protectionNode.push($('<b>' + conv({ hans: '无保护', hant: '無保護' }) + '</b>')[0]);
}
return protectionNode;
};
Twinkle.addInitCallback(Twinkle.protect, 'protect');
})(jQuery);
// </nowiki>
9f1f747d0c5ca94435441175cb8f288a62d9f2e8
MediaWiki:Gadget-friendlytag.js
8
161
325
324
2024-08-03T04:07:26Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** friendlytag.js: Tag module
****************************************
* Mode of invocation: Tab ("Tag")
* Active on: Existing articles and drafts; file pages with a corresponding file
* which is local (not on Commons); all redirects
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.tag = function friendlytag() {
// redirect tagging
if (Morebits.isPageRedirect()) {
Twinkle.tag.mode = conv({ hans: '重定向', hant: '重新導向' });
Twinkle.tag.modeEn = 'redirect';
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记重定向', hant: '標記重新導向' }));
// file tagging
} else if (mw.config.get('wgNamespaceNumber') === 6 && !document.getElementById('mw-sharedupload') && document.getElementById('mw-imagepage-section-filehistory')) {
Twinkle.tag.mode = conv({ hans: '文件', hant: '檔案' });
Twinkle.tag.modeEn = 'file';
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记文件', hant: '標記檔案' }));
// article/draft tagging
} else if (([0, 118].indexOf(mw.config.get('wgNamespaceNumber')) !== -1 && mw.config.get('wgCurRevisionId')) || (Morebits.pageNameNorm === Twinkle.getPref('sandboxPage'))) {
Twinkle.tag.mode = conv({ hans: '条目', hant: '條目' });
Twinkle.tag.modeEn = 'article';
// Can't remove tags when not viewing current version
Twinkle.tag.canRemove = (mw.config.get('wgCurRevisionId') === mw.config.get('wgRevisionId')) &&
// Disabled on latest diff because the diff slider could be used to slide
// away from the latest diff without causing the script to reload
!mw.config.get('wgDiffNewId');
Twinkle.addPortletLink(Twinkle.tag.callback, conv({ hans: '标记', hant: '標記' }), 'friendly-tag', conv({ hans: '标记条目', hant: '標記條目' }));
}
};
Twinkle.tag.checkedTags = [];
Twinkle.tag.callback = function friendlytagCallback() {
var Window = new Morebits.simpleWindow(630, Twinkle.tag.modeEn === 'article' ? 500 : 400);
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '标记设置', hant: '標記設定' }), 'WP:TW/PREF#tag');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#tag');
var form = new Morebits.quickForm(Twinkle.tag.callback.evaluate);
form.append({
type: 'input',
label: conv({ hans: '筛选标记列表:', hant: '篩選標記列表:' }),
name: 'quickfilter',
size: '30',
event: function twinkletagquickfilter() {
// flush the DOM of all existing underline spans
$allCheckboxDivs.find('.search-hit').each(function(i, e) {
var label_element = e.parentElement;
// This would convert <label>Hello <span class=search-hit>wo</span>rld</label>
// to <label>Hello world</label>
label_element.innerHTML = label_element.textContent;
});
if (this.value) {
$allCheckboxDivs.hide();
$allHeaders.hide();
var searchString = this.value;
var searchRegex = new RegExp(mw.util.escapeRegExp(searchString), 'i');
$allCheckboxDivs.find('label').each(function () {
var label_text = this.textContent;
var searchHit = searchRegex.exec(label_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
this.parentElement.style.display = 'block'; // show
}
});
} else {
$allCheckboxDivs.show();
$allHeaders.show();
}
}
});
switch (Twinkle.tag.modeEn) {
case 'article':
Window.setTitle(conv({ hans: '条目维护标记', hant: '條目維護標記' }));
// Build sorting and lookup object flatObject, which is always
// needed but also used to generate the alphabetical list
// Would be infinitely better with Object.values, but, alas, IE 11
Twinkle.tag.article.flatObject = {};
Twinkle.tag.article.tagList.forEach(function(group) {
group.value.forEach(function(subgroup) {
if (subgroup.value) {
subgroup.value.forEach(function(item) {
Twinkle.tag.article.flatObject[item.tag] = { description: item.description, excludeMI: !!item.excludeMI };
});
} else {
Twinkle.tag.article.flatObject[subgroup.tag] = { description: subgroup.description, excludeMI: !!subgroup.excludeMI };
}
});
});
form.append({
type: 'select',
name: 'sortorder',
label: conv({ hans: '查看列表:', hant: '檢視列表:' }),
tooltip: conv({ hans: '您可以在Twinkle参数设置(WP:TWPREFS)中更改此项。', hant: '您可以在Twinkle偏好設定(WP:TWPREFS)中更改此項。' }),
event: Twinkle.tag.updateSortOrder,
list: [
{ type: 'option', value: 'cat', label: conv({ hans: '按类型', hant: '按類別' }), selected: Twinkle.getPref('tagArticleSortOrder') === 'cat' },
{ type: 'option', value: 'alpha', label: '按字母', selected: Twinkle.getPref('tagArticleSortOrder') === 'alpha' }
]
});
if (!Twinkle.tag.canRemove) {
var divElement = document.createElement('div');
divElement.innerHTML = conv({ hans: '要移除现有维护标记,请从当前条目版本中打开“标记”菜单', hant: '要移除現有維護標記,請從目前條目版本中打開「標記」選單' });
form.append({
type: 'div',
name: 'untagnotice',
label: divElement
});
}
form.append({
type: 'div',
id: 'tagWorkArea',
className: 'morebits-scrollbox',
style: 'max-height: 28em'
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如可能,合并入{{multiple issues}}', hant: '如可能,合併入{{multiple issues}}' }),
value: 'group',
name: 'group',
tooltip: conv({
hans: '如果加入{{multiple issues}}支持的三个以上的模板,所有支持的模板都会被合并入{{multiple issues}}模板中。',
hant: '如果加入{{multiple issues}}支援的三個以上的模板,所有支援的模板都會被合併入{{multiple issues}}模板中。'
}),
checked: Twinkle.getPref('groupByDefault')
}
]
});
form.append({
type: 'input',
label: '理由:',
name: 'reason',
tooltip: conv({
hans: '附加于编辑摘要的可选理由,例如指出条目内容的哪些部分有问题或移除模板的理由,但如果理由很长则应该发表在讨论页。',
hant: '附加於編輯摘要的可選理由,例如指出條目內容的哪些部分有問題或移除模板的理由,但如果理由很長則應該發表在討論頁。'
}),
size: '80'
});
break;
case 'file':
Window.setTitle(conv({ hans: '文件维护标记', hant: '檔案維護標記' }));
Twinkle.tag.fileList.forEach(function(group) {
if (group.buildFilename) {
group.value.forEach(function(el) {
el.subgroup = {
type: 'input',
label: conv({ hans: '替换的文件:', hant: '替換的檔案:' }),
tooltip: conv({ hans: '输入替换此文件的文件名称(必填)', hant: '輸入替換此檔案的檔案名稱(必填)' }),
name: el.value.replace(/ /g, '_') + 'File'
};
});
}
form.append({ type: 'header', label: group.key });
form.append({ type: 'checkbox', name: 'tags', list: group.value });
});
if (Twinkle.getPref('customFileTagList').length) {
form.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
form.append({ type: 'checkbox', name: 'tags', list: Twinkle.getPref('customFileTagList') });
}
break;
case 'redirect':
Window.setTitle(conv({ hans: '重定向标记', hant: '重新導向標記' }));
var i = 1;
Twinkle.tag.redirectList.forEach(function(group) {
form.append({ type: 'header', id: 'tagHeader' + i, label: group.key });
form.append({
type: 'checkbox',
name: 'tags',
list: group.value.map(function (item) {
return { value: item.tag, label: '{{' + item.tag + '}}:' + item.description, subgroup: item.subgroup };
})
});
});
if (Twinkle.getPref('customRedirectTagList').length) {
form.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
form.append({ type: 'checkbox', name: 'tags', list: Twinkle.getPref('customRedirectTagList') });
}
break;
default:
alert('Twinkle.tag:未知模式 ' + Twinkle.tag.mode);
break;
}
if (document.getElementsByClassName('patrollink').length) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '标记页面为已巡查', hant: '標記頁面為已巡查' }),
value: 'patrol',
name: 'patrol',
checked: Twinkle.getPref('markTaggedPagesAsPatrolled')
}
]
});
}
form.append({ type: 'submit', className: 'tw-tag-submit' });
var result = form.render();
Window.setContent(result);
Window.display();
// for quick filter:
$allCheckboxDivs = $(result).find('[name$=tags]').parent();
$allHeaders = $(result).find('h5');
result.quickfilter.focus(); // place cursor in the quick filter field as soon as window is opened
result.quickfilter.autocomplete = 'off'; // disable browser suggestions
result.quickfilter.addEventListener('keypress', function(e) {
if (e.keyCode === 13) { // prevent enter key from accidentally submitting the form
e.preventDefault();
return false;
}
});
if (Twinkle.tag.modeEn === 'article') {
Twinkle.tag.alreadyPresentTags = [];
if (Twinkle.tag.canRemove) {
// Look for existing maintenance tags in the lead section and put them in array
// All tags are HTML table elements that are direct children of .mw-parser-output,
// except when they are within {{multiple issues}}
$('.mw-parser-output').children().each(function parsehtml(i, e) {
// break out on encountering the first heading, which means we are no
// longer in the lead section
if (e.tagName === 'H2') {
return false;
}
// The ability to remove tags depends on the template's {{ambox}} |name=
// parameter bearing the template's correct name (preferably) or a name that at
// least redirects to the actual name
// All tags have their first class name as "box-" + template name
if (e.className.indexOf('box-') === 0) {
if (e.classList[0] === 'box-问题条目') {
$(e).find('.ambox').each(function(idx, e) {
if (e.classList[0].indexOf('box-') === 0) {
var tag = e.classList[0].slice('box-'.length).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
}
});
return true; // continue
}
var tag = e.classList[0].slice('box-'.length).replace(/_/g, ' ');
Twinkle.tag.alreadyPresentTags.push(tag);
}
});
// {{Uncategorized}} and {{Improve categories}} are usually placed at the end
if ($('.box-Uncategorized').length) {
Twinkle.tag.alreadyPresentTags.push('Uncategorized');
}
if ($('.box-Improve_categories').length) {
Twinkle.tag.alreadyPresentTags.push('Improve categories');
}
}
// Add status text node after Submit button
var statusNode = document.createElement('small');
statusNode.id = 'tw-tag-status';
Twinkle.tag.status = {
// initial state; defined like this because these need to be available for reference
// in the click event handler
numAdded: 0,
numRemoved: 0
};
$('button.tw-tag-submit').after(statusNode);
// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sortorder.dispatchEvent(evt);
} else {
// Redirects and files: Add a link to each template's description page
Morebits.quickForm.getElements(result, 'tags').forEach(generateLinks);
}
};
// $allCheckboxDivs and $allHeaders are defined globally, rather than in the
// quickfilter event function, to avoid having to recompute them on every keydown
var $allCheckboxDivs, $allHeaders;
Twinkle.tag.updateSortOrder = function(e) {
var form = e.target.form;
var sortorder = e.target.value;
Twinkle.tag.checkedTags = form.getChecked('tags');
var container = new Morebits.quickForm.element({ type: 'fragment' });
// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: '{{' + tag + '}}: ' + description };
if (Twinkle.tag.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
switch (tag) {
case 'Expand language':
checkbox.subgroup = [
{
name: 'expandLanguage',
type: 'input',
label: conv({ hans: '外语版本语言代码(必填):', hant: '外語版本語言代碼(必填):' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
},
{
name: 'expandLanguage2',
type: 'input',
label: conv({ hans: '外语版本语言代码:', hant: '外語版本語言代碼:' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle2',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
},
{
name: 'expandLanguage3',
type: 'input',
label: conv({ hans: '外语版本语言代码:', hant: '外語版本語言代碼:' })
},
{
type: 'checkbox',
list: [
{
name: 'highQualityArticle3',
label: conv({ hans: '高品质条目', hant: '高品質條目' })
}
]
}
];
break;
case 'Expert needed':
checkbox.subgroup = [
{
name: 'expert',
type: 'input',
label: conv({ hans: '哪个领域的专家(必填):', hant: '哪個領域的專家(必填):' }),
tooltip: conv({ hans: '必填,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '必填,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
},
{
name: 'expert2',
type: 'input',
label: conv({ hans: '哪个领域的专家:', hant: '哪個領域的專家:' }),
tooltip: conv({ hans: '可选,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '可選,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
},
{
name: 'expert3',
type: 'input',
label: conv({ hans: '哪个领域的专家:', hant: '哪個領域的專家:' }),
tooltip: conv({ hans: '可选,可参考 Category:需要专业人士关注的页面 使用现存的分类。', hant: '可選,可參考 Category:需要專業人士關注的頁面 使用現存的分類。' })
}
];
break;
case 'Merge':
case 'Merge from':
case 'Merge to':
var otherTagName = 'Merge';
switch (tag) {
case 'Merge from':
otherTagName = 'Merge to';
break;
case 'Merge to':
otherTagName = 'Merge from';
break;
// no default
}
checkbox.subgroup = [
{
name: 'mergeTarget',
type: 'input',
label: conv({ hans: '其他条目:', hant: '其他條目:' }),
tooltip: conv({ hans: '如指定多个条目,请用管道符分隔:条目甲|条目乙', hant: '如指定多個條目,請用管道符分隔:條目甲|條目乙' })
},
{
type: 'checkbox',
list: [
{
name: 'mergeTagOther',
label: '用{{' + otherTagName + conv({ hans: '}}标记其他条目', hant: '}}標記其他條目' }),
checked: true,
tooltip: conv({ hans: '仅在只输入了一个条目名时可用', hant: '僅在只輸入了一個條目名時可用' })
}
]
}
];
if (mw.config.get('wgNamespaceNumber') === 0) {
checkbox.subgroup.push({
name: 'mergeReason',
type: 'textarea',
label: conv({
hans: '合并理由(会被贴上' + (tag === 'Merge to' ? '其他' : '这') + '条目的讨论页):',
hant: '合併理由(會被貼上' + (tag === 'Merge to' ? '其他' : '這') + '條目的討論頁):'
}),
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。仅在只输入了一个条目名时可用。', hant: '可選,但強烈推薦。如不需要請留空。僅在只輸入了一個條目名時可用。' })
});
}
break;
case 'Missing information':
checkbox.subgroup = {
name: 'missingInformation',
type: 'input',
label: conv({ hans: '缺少的内容(必填):', hant: '缺少的內容(必填):' }),
tooltip: conv({ hans: '必填,显示为“缺少有关……的信息。”', hant: '必填,顯示為「缺少有關……的資訊。」' })
};
break;
case 'Notability':
checkbox.subgroup = {
name: 'notability',
type: 'select',
list: [
{ label: '{{Notability}}:' + conv({ hans: '通用的关注度指引', hant: '通用的關注度指引' }), value: 'none' },
{ label: '{{Notability|Astro}}:' + conv({ hans: '天体', hant: '天體' }), value: 'Astro' },
{ label: '{{Notability|Biographies}}:' + conv({ hans: '人物传记', hant: '人物傳記' }), value: 'Biographies' },
{ label: '{{Notability|Book}}:' + conv({ hans: '书籍', hant: '書籍' }), value: 'Book' },
{ label: '{{Notability|Cyclone}}:' + conv({ hans: '气旋', hant: '氣旋' }), value: 'Cyclone' },
{ label: '{{Notability|Fiction}}:' + conv({ hans: '虚构事物', hant: '虛構事物' }), value: 'Fiction' },
{ label: '{{Notability|Geographic}}:' + conv({ hans: '地理特征', hant: '地理特徵' }), value: 'Geographic' },
{ label: '{{Notability|Geometry}}:' + conv({ hans: '几何图形', hant: '幾何圖形' }), value: 'Geometry' },
{ label: '{{Notability|Invention}}:' + conv({ hans: '发明、研究', hant: '發明、研究' }), value: 'Invention' },
{ label: '{{Notability|Music}}:' + conv({ hans: '音乐', hant: '音樂' }), value: 'Music' },
{ label: '{{Notability|Numbers}}:' + conv({ hans: '数字', hant: '數字' }), value: 'Numbers' },
{ label: '{{Notability|Organizations}}:' + conv({ hans: '组织', hant: '組織' }), value: 'Organizations' },
{ label: '{{Notability|Property}}:' + conv({ hans: '性质表', hant: '性質表' }), value: 'Property' },
{ label: '{{Notability|Traffic}}:' + '交通', value: 'Traffic' },
{ label: '{{Notability|Web}}:' + conv({ hans: '网站、网络内容', hant: '網站、網路內容' }) + '(非正式指引)', value: 'Web' }
]
};
break;
case 'Requested move':
checkbox.subgroup = [
{
name: 'moveTarget',
type: 'input',
label: conv({ hans: '新名称:', hant: '新名稱:' })
},
{
name: 'moveReason',
type: 'textarea',
label: conv({ hans: '移动理由(会被粘贴该条目的讨论页):', hant: '移動理由(會被貼上該條目的討論頁):' }),
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。', hant: '可選,但強烈推薦。如不需要請留空。' })
}
];
break;
case 'Split':
checkbox.subgroup = [
{
name: 'target1',
type: 'input',
label: conv({ hans: '页面名1:', hant: '頁面名1:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
},
{
name: 'target2',
type: 'input',
label: conv({ hans: '页面名2:', hant: '頁面名2:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
},
{
name: 'target3',
type: 'input',
label: conv({ hans: '页面名3:', hant: '頁面名3:' }),
tooltip: conv({ hans: '可选。', hant: '可選。' })
}
];
break;
case 'Cleanup':
checkbox.subgroup = [
{
name: 'cleanupReason',
type: 'input',
label: '需要清理的理由',
tooltip: conv({ hans: '可选,但强烈推荐。如不需要请留空。', hant: '可選,但強烈推薦。如不需要請留空。' })
}
];
break;
default:
break;
}
return checkbox;
};
var makeCheckboxesForAlreadyPresentTags = function() {
container.append({ type: 'header', id: 'tagHeader0', label: conv({ hans: '已放置的维护标记', hant: '已放置的維護標記' }) });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv0' });
var checkboxes = [];
var unCheckedTags = e.target.form.getUnchecked('existingTags');
Twinkle.tag.alreadyPresentTags.forEach(function(tag) {
var checkbox =
{
value: tag,
label: '{{' + tag + '}}' + (Twinkle.tag.article.flatObject[tag] ? ': ' + Twinkle.tag.article.flatObject[tag].description : ''),
checked: unCheckedTags.indexOf(tag) === -1
};
checkboxes.push(checkbox);
});
subdiv.append({
type: 'checkbox',
name: 'existingTags',
list: checkboxes
});
};
if (sortorder === 'cat') { // categorical sort order
// function to iterate through the tags and create a checkbox for each one
var doCategoryCheckboxes = function(subdiv, subgroup) {
var checkboxes = [];
$.each(subgroup, function(k, item) {
if (Twinkle.tag.alreadyPresentTags.indexOf(item.tag) === -1) {
checkboxes.push(makeCheckbox(item.tag, item.description));
}
});
subdiv.append({
type: 'checkbox',
name: 'tags',
list: checkboxes
});
};
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
}
var i = 1;
// go through each category and sub-category and append lists of checkboxes
Twinkle.tag.article.tagList.forEach(function(group) {
container.append({ type: 'header', id: 'tagHeader' + i, label: group.key });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv' + i++ });
if (group.value[0].tag) {
doCategoryCheckboxes(subdiv, group.value);
} else {
group.value.forEach(function(subgroup) {
subdiv.append({ type: 'div', label: [ Morebits.htmlNode('b', subgroup.key) ] });
doCategoryCheckboxes(subdiv, subgroup.value);
});
}
});
} else { // alphabetical sort order
if (Twinkle.tag.alreadyPresentTags.length > 0) {
makeCheckboxesForAlreadyPresentTags();
container.append({ type: 'header', id: 'tagHeader1', label: conv({ hans: '可用的维护标记', hant: '可用的維護標記' }) });
}
// Avoid repeatedly resorting
Twinkle.tag.article.alphabeticalList = Twinkle.tag.article.alphabeticalList || Object.keys(Twinkle.tag.article.flatObject).sort();
var checkboxes = [];
Twinkle.tag.article.alphabeticalList.forEach(function(tag) {
if (Twinkle.tag.alreadyPresentTags.indexOf(tag) === -1) {
checkboxes.push(makeCheckbox(tag, Twinkle.tag.article.flatObject[tag].description));
}
});
container.append({
type: 'checkbox',
name: 'tags',
list: checkboxes
});
}
// append any custom tags
if (Twinkle.getPref('customTagList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
container.append({ type: 'checkbox', name: 'tags',
list: Twinkle.getPref('customTagList').map(function(el) {
el.checked = Twinkle.tag.checkedTags.indexOf(el.value) !== -1;
return el;
})
});
}
var $workarea = $(form).find('#tagWorkArea');
var rendered = container.render();
$workarea.empty().append(rendered);
// for quick filter:
$allCheckboxDivs = $workarea.find('[name=tags], [name=existingTags]').parent();
$allHeaders = $workarea.find('h5, .quickformDescription');
form.quickfilter.value = ''; // clear search, because the search results are not preserved over mode change
form.quickfilter.focus();
// style adjustments
$workarea.find('h5').css({ 'font-size': '110%' });
$workarea.find('h5:not(:first-child)').css({ 'margin-top': '1em' });
$workarea.find('div').filter(':has(span.quickformDescription)').css({ 'margin-top': '0.4em' });
Morebits.quickForm.getElements(form, 'existingTags').forEach(generateLinks);
Morebits.quickForm.getElements(form, 'tags').forEach(generateLinks);
// tally tags added/removed, update statusNode text
var statusNode = document.getElementById('tw-tag-status');
$('[name=tags], [name=existingTags]').click(function() {
if (this.name === 'tags') {
Twinkle.tag.status.numAdded += this.checked ? 1 : -1;
} else if (this.name === 'existingTags') {
Twinkle.tag.status.numRemoved += this.checked ? -1 : 1;
}
var firstPart = '加入' + Twinkle.tag.status.numAdded + conv({ hans: '个标记', hant: '個標記' });
var secondPart = '移除' + Twinkle.tag.status.numRemoved + conv({ hans: '个标记', hant: '個標記' });
statusNode.textContent =
(Twinkle.tag.status.numAdded ? ' ' + firstPart : '') +
(Twinkle.tag.status.numRemoved ? (Twinkle.tag.status.numAdded ? ';' : ' ') + secondPart : '');
});
};
/**
* Adds a link to each template's description page
* @param {Morebits.quickForm.element} checkbox associated with the template
*/
var generateLinks = function(checkbox) {
var link = Morebits.htmlNode('a', '>');
link.setAttribute('class', 'tag-template-link');
var tagname = checkbox.values;
link.setAttribute('href', mw.util.getUrl(
(tagname.indexOf(':') === -1 ? 'Template:' : '') +
(tagname.indexOf('|') === -1 ? tagname : tagname.slice(0, tagname.indexOf('|')))
));
link.setAttribute('target', '_blank');
$(checkbox).parent().append(['\u00A0', link]);
};
// Tags for ARTICLES start here
Twinkle.tag.article = {};
// Tags arranged by category; will be used to generate the alphabetical list,
// but tags should be in alphabetical order within the categories
// excludeMI: true indicate a tag that *does not* work inside {{multiple issues}}
// Add new categories with discretion - the list is long enough as is!
Twinkle.tag.article.tagList = [{
key: conv({ hans: '清理和维护模板', hant: '清理和維護模板' }),
value: [{
key: conv({ hans: '常规清理', hant: '常規清理' }),
value: [
{ tag: 'Cleanup', description: conv({ hans: '可能需要进行清理,以符合维基百科的质量标准', hant: '可能需要進行清理,以符合維基百科的質量標準' }) },
{ tag: 'Cleanup rewrite', description: conv({ hans: '不符合维基百科的质量标准,需要完全重写', hant: '不符合維基百科的質量標準,需要完全重寫' }) },
{ tag: 'Cleanup-jargon', description: conv({ hans: '包含过多行话或专业术语,可能需要简化或提出进一步解释', hant: '包含過多行話或專業術語,可能需要簡化或提出進一步解釋' }) },
{ tag: 'Copy edit', description: conv({ hans: '需要编修,以确保文法、用词、语气、格式、标点等使用恰当', hant: '需要編修,以確保文法、用詞、語氣、格式、標點等使用恰當' }) }
]
},
{
key: conv({ hans: '可能多余的内容', hant: '可能多餘的內容' }),
value: [
{ tag: 'Copypaste', description: conv({ hans: '内容可能是从某个来源处拷贝后粘贴', hant: '內容可能是從某個來源處拷貝後貼上' }) },
{ tag: 'External links', description: conv({ hans: '使用外部链接的方式可能不符合维基百科的方针或指引', hant: '使用外部連結的方式可能不符合維基百科的方針或指引' }) },
{ tag: 'Non-free', description: conv({ hans: '可能过多或不当地使用了受著作权保护的文字、图像或多媒体文件', hant: '可能過多或不當地使用了受版權保護的文字、圖像或多媒體檔案' }) }
]
},
{
key: conv({ hans: '结构和导言', hant: '結構和導言' }),
value: [
{ tag: 'Lead too long', description: conv({ hans: '导言部分也许过于冗长', hant: '導言部分也許過於冗長' }) },
{ tag: 'Lead too short', description: conv({ hans: '导言部分也许不足以概括其内容', hant: '導言部分也許不足以概括其內容' }) },
{ tag: 'Very long', description: conv({ hans: '可能过于冗长', hant: '可能過於冗長' }) }
]
},
{
key: conv({ hans: '虚构作品相关清理', hant: '虛構作品相關清理' }),
value: [
{ tag: 'In-universe', description: conv({ hans: '使用小说故事内的观点描述一个虚构事物', hant: '使用小說故事內的觀點描述一個虛構事物' }) },
{ tag: 'Long plot', description: conv({ hans: '可能包含过于详细的剧情摘要', hant: '可能包含過於詳細的劇情摘要' }) }
]
}]
},
{
key: conv({ hans: '常规条目问题', hant: '常規條目問題' }),
value: [{
key: '重要性和知名度',
value: [
{ tag: 'Notability', description: conv({ hans: '可能不符合通用关注度指引', hant: '可能不符合通用關注度指引' }), excludeMI: true }, // has a subgroup with subcategories
{ tag: 'Notability Unreferenced', description: conv({ hans: '可能具备关注度,但需要来源加以彰显', hant: '可能具備關注度,但需要來源加以彰顯' }) }
]
},
{
key: conv({ hans: '写作风格', hant: '寫作風格' }),
value: [
{ tag: 'Advert', description: conv({ hans: '类似广告或宣传性内容', hant: '類似廣告或宣傳性內容' }) },
{ tag: 'Fanpov', description: conv({ hans: '类似爱好者网页', hant: '類似愛好者網頁' }) },
{ tag: 'How-to', description: conv({ hans: '包含指南或教学内容', hant: '包含指南或教學內容' }) },
{ tag: 'Inappropriate person', description: conv({ hans: '使用不适当的第一人称和第二人称', hant: '使用不適當的第一人稱和第二人稱' }) },
{ tag: 'Newsrelease', description: conv({ hans: '阅读起来像是新闻稿及包含过度的宣传性语调', hant: '閱讀起來像是新聞稿及包含過度的宣傳性語調' }) },
{ tag: 'Prose', description: conv({ hans: '使用了日期或时间列表式记述,需要改写为连贯的叙述性文字', hant: '使用了日期或時間列表式記述,需要改寫為連貫的敘述性文字' }) },
{ tag: 'Review', description: conv({ hans: '阅读起来类似评论,需要清理', hant: '閱讀起來類似評論,需要清理' }) },
{ tag: 'Tone', description: conv({ hans: '语调或风格可能不适合百科全书的写作方式', hant: '語調或風格可能不適合百科全書的寫作方式' }) }
]
},
{
key: conv({ hans: '内容', hant: '內容' }),
value: [
{ tag: 'Expand language', description: conv({ hans: '可以根据其他语言版本扩展', hant: '可以根據其他語言版本擴充' }) }, // these three have a subgroup with several options
{ tag: 'Missing information', description: '缺少必要的信息' }, // these three have a subgroup with several options
{ tag: 'Substub', description: conv({ hans: '过于短小', hant: '過於短小' }), excludeMI: true },
{ tag: 'Unencyclopedic', description: conv({ hans: '可能不适合写入百科全书', hant: '可能不適合寫入百科全書' }) }
]
},
{
key: conv({ hans: '信息和细节', hant: '資訊和細節' }),
value: [
{ tag: 'Expert needed', description: conv({ hans: '需要精通或熟悉本主题的专业人士(专家)参与及协助编辑', hant: '需要精通或熟悉本主題的專業人士(專家)參與及協助編輯' }) },
{ tag: 'Overly detailed', description: conv({ hans: '包含太多过度细节内容', hant: '包含太多過度細節內容' }) },
{ tag: 'Trivia', description: conv({ hans: '应避免有陈列杂项、琐碎资料的部分', hant: '應避免有陳列雜項、瑣碎資料的部分' }) }
]
},
{
key: conv({ hans: '时间性', hant: '時間性' }),
value: [
{ tag: 'Current', description: conv({ hans: '记述新闻动态', hant: '記述新聞動態' }), excludeMI: true }, // Works but not intended for use in MI
{ tag: 'Update', description: conv({ hans: '当前条目或章节需要更新', hant: '當前條目或章節需要更新' }) }
]
},
{
key: conv({ hans: '中立、偏见和事实准确性', hant: '中立、偏見和事實準確性' }),
value: [
{ tag: 'Autobiography', description: conv({ hans: '类似一篇自传,或内容主要由条目描述的当事人或组织撰写、编辑', hant: '類似一篇自傳,或內容主要由條目描述的當事人或組織撰寫、編輯' }) },
{ tag: 'COI', description: conv({ hans: '主要贡献者与本条目所宣扬的内容可能存在利益冲突', hant: '主要貢獻者與本條目所宣揚的內容可能存在利益衝突' }) },
{ tag: 'Disputed', description: conv({ hans: '内容疑欠准确,有待查证', hant: '內容疑欠準確,有待查證' }) },
{ tag: 'Globalize', description: conv({ hans: '仅具有一部分地区的信息或观点', hant: '僅具有一部分地區的資訊或觀點' }) },
{ tag: 'Hoax', description: conv({ hans: '真实性被质疑', hant: '真實性被質疑' }) },
{ tag: 'POV', description: conv({ hans: '中立性有争议。内容、语调可能带有明显的个人观点或地方色彩', hant: '中立性有爭議。內容、語調可能帶有明顯的個人觀點或地方色彩' }) },
{ tag: 'Self-contradictory', description: conv({ hans: '内容自相矛盾', hant: '內容自相矛盾' }) },
{ tag: 'Weasel', description: conv({ hans: '语义模棱两可而损及其中立性或准确性', hant: '語意模棱兩可而損及其中立性或準確性' }) }
]
},
{
key: conv({ hans: '可供查证和来源', hant: '可供查證和來源' }),
value: [
{ tag: 'BLPdispute', description: conv({ hans: '可能违反了维基百科关于生者传记的方针', hant: '可能違反了維基百科關於生者傳記的方針' }) },
{ tag: 'BLPsources', description: conv({ hans: '生者传记需要补充更多可供查证的来源', hant: '生者傳記需要補充更多可供查證的來源' }) },
{ tag: 'BLP unsourced', description: conv({ hans: '生者传记没有列出任何参考或来源', hant: '生者傳記沒有列出任何參考或來源' }) },
{ tag: 'Citecheck', description: conv({ hans: '可能包含不适用或被曲解的引用资料,部分内容的准确性无法被证实', hant: '可能包含不適用或被曲解的引用資料,部分內容的準確性無法被證實' }) },
{ tag: 'More footnotes needed', description: conv({ hans: '因为文内引用不足,部分字句的来源仍然不明', hant: '因為文內引用不足,部分字句的來源仍然不明' }) },
{ tag: 'No footnotes', description: conv({ hans: '因为没有内文引用而来源仍然不明', hant: '因為沒有內文引用而來源仍然不明' }) },
{ tag: 'Onesource', description: conv({ hans: '极大或完全地依赖于某个单一的来源', hant: '極大或完全地依賴於某個單一的來源' }) },
{ tag: 'Original research', description: conv({ hans: '可能包含原创研究或未查证内容', hant: '可能包含原創研究或未查證內容' }) },
{ tag: 'Primarysources', description: conv({ hans: '依赖第一手来源', hant: '依賴第一手來源' }) },
{ tag: 'Refimprove', description: conv({ hans: '需要补充更多来源', hant: '需要補充更多來源' }) },
{ tag: 'Unreferenced', description: conv({ hans: '没有列出任何参考或来源', hant: '沒有列出任何參考或來源' }) }
]
}]
},
{
key: conv({ hans: '具体内容问题', hant: '具體內容問題' }),
value: [{
key: conv({ hans: '语言', hant: '語言' }),
value: [
{ tag: 'NotMandarin', description: conv({ hans: '包含过多不是现代标准汉语的内容', hant: '包含過多不是現代標準漢語的內容' }), excludeMI: true },
{ tag: 'Rough translation', description: conv({ hans: '翻译品质不佳', hant: '翻譯品質不佳' }) }
]
},
{
key: conv({ hans: '链接', hant: '連結' }),
value: [
{ tag: 'Dead end', description: conv({ hans: '需要加上内部链接以构筑百科全书的链接网络', hant: '需要加上內部連結以構築百科全書的連結網絡' }) },
{ tag: 'Orphan', description: conv({ hans: '没有或只有很少链入页面', hant: '沒有或只有很少連入頁面' }) },
{ tag: 'Overlinked', description: conv({ hans: '含有过多、重复、或不必要的内部链接', hant: '含有過多、重複、或不必要的內部連結' }) },
{ tag: 'Underlinked', description: conv({ hans: '需要更多内部链接以构筑百科全书的链接网络', hant: '需要更多內部連結以構築百科全書的連結網絡' }) }
]
},
{
key: conv({ hans: '参考技术', hant: '參考技術' }),
value: [
{ tag: 'Citation style', description: conv({ hans: '引用需要进行清理', hant: '引用需要進行清理' }) }
]
},
{
key: conv({ hans: '分类', hant: '分類' }),
value: [
{ tag: 'Improve categories', description: conv({ hans: '需要更多页面分类', hant: '需要更多頁面分類' }), excludeMI: true },
{ tag: 'Uncategorized', description: conv({ hans: '缺少页面分类', hant: '缺少頁面分類' }), excludeMI: true }
]
}]
},
{
key: conv({ hans: '合并、拆分、移动', hant: '合併、拆分、移動' }),
value: [
{ tag: 'Merge from', description: conv({ hans: '建议将页面并入本页面', hant: '建議將頁面併入本頁面' }), excludeMI: true },
{ tag: 'Merge to', description: conv({ hans: '建议将此页面并入页面', hant: '建議將此頁面併入頁面' }), excludeMI: true },
{ tag: 'Merge', description: conv({ hans: '建议此页面与页面合并', hant: '建議此頁面與頁面合併' }), excludeMI: true },
{ tag: 'Requested move', description: conv({ hans: '建议将此页面移动到新名称', hant: '建議將此頁面移動到新名稱' }), excludeMI: true },
{ tag: 'Split', description: conv({ hans: '建议将此页面分割为多个页面', hant: '建議將此頁面分割為多個頁面' }), excludeMI: true }
]
}];
// Tags for REDIRECTS start here
// Not by policy, but the list roughly approximates items with >500
// transclusions from Template:R template index
Twinkle.tag.redirectList = [{
key: '常用模板',
value: [
{ tag: conv({ hans: '合并重定向', hant: '合併重定向' }), description: conv({ hans: '保持页面题名至相应主条目,令页面内容在合并后仍能保存其编辑历史', hant: '保持頁面題名至相應主條目,令頁面內容在合併後仍能儲存其編輯歷史' }) },
{ tag: conv({ hans: '简繁重定向', hant: '簡繁重定向' }), description: conv({ hans: '引导简体至繁体,或繁体至简体', hant: '引導簡體至繁體,或繁體至簡體' }) },
{ tag: conv({ hans: '关注度重定向', hant: '關注度重定向' }), description: conv({ hans: '缺乏关注度的子主题向有关注度的母主题的重定向', hant: '缺乏關注度的子主題向有關注度的母主題的重定向' }) },
{ tag: '模板重定向', description: conv({ hans: '指向模板的重定向页面', hant: '指向模板的重定向頁面' }) },
{ tag: conv({ hans: '别名重定向', hant: '別名重定向' }), description: conv({ hans: '标题的其他名称、笔名、绰号、同义字等', hant: '標題的其他名稱、筆名、綽號、同義字等' }) },
{ tag: conv({ hans: '译名重定向', hant: '譯名重定向' }), description: conv({ hans: '人物、作品等各项事物的其他翻译名称', hant: '人物、作品等各項事物的其他翻譯名稱' }) },
{ tag: conv({ hans: '缩写重定向', hant: '縮寫重定向' }), description: conv({ hans: '标题缩写', hant: '標題縮寫' }) },
{ tag: conv({ hans: '拼写重定向', hant: '拼寫重定向' }), description: conv({ hans: '标题的其他不同拼写', hant: '標題的其他不同拼寫' }) },
{ tag: conv({ hans: '错字重定向', hant: '錯字重定向' }), description: conv({ hans: '纠正标题的常见错误拼写或误植', hant: '糾正標題的常見錯誤拼寫或誤植' }) },
{ tag: conv({ hans: '旧名重定向', hant: '舊名重定向' }), description: conv({ hans: '将事物早前的名称引导至更改后的主题', hant: '將事物早前的名稱引導至更改後的主題' }) },
{ tag: '全名重定向', description: conv({ hans: '标题的完整或更完整名称', hant: '標題的完整或更完整名稱' }) },
{ tag: '短名重定向', description: conv({ hans: '完整标题名称或人物全名的部分、不完整的名称或简称', hant: '完整標題名稱或人物全名的部分、不完整的名稱或簡稱' }) },
{ tag: '姓氏重定向', description: '人物姓氏' },
{ tag: '名字重定向', description: '人物人名' },
{ tag: '本名重定向', description: '人物本名' },
{
tag: '非中文重定向',
description: conv({ hans: '非中文标题', hant: '非中文標題' }),
subgroup: [
{
name: 'altLangFrom',
type: 'input',
label: '本重新導向的語言(可選)',
tooltip: '輸入重新導向名稱所使用語言的ISO 639代碼,例如en代表英語,代碼可參見 Template:ISO_639_name'
}
]
},
{ tag: '日文重定向', description: conv({ hans: '日语名称', hant: '日語名稱' }) }
]
},
{
key: '偶用模板',
value: [
{ tag: '角色重定向', description: conv({ hans: '电视剧、电影、书籍等作品的角色', hant: '電視劇、電影、書籍等作品的角色' }) },
{ tag: conv({ hans: '章节重定向', hant: '章節重定向' }), description: conv({ hans: '导向至较高密度组织的页面', hant: '導向至較高密度組織的頁面' }) },
{ tag: '列表重定向', description: conv({ hans: '导向至低密度的列表', hant: '導向至低密度的列表' }) },
{ tag: '可能性重定向', description: conv({ hans: '导向至当前提供内容更为详尽的目标页面', hant: '導向至當前提供內容更為詳盡的目標頁面' }) },
{ tag: conv({ hans: '关联字重定向', hant: '關聯字重定向' }), description: conv({ hans: '标题名称关联字', hant: '標題名稱關聯字' }) },
{
tag: conv({ hans: '条目请求重定向', hant: '條目請求重定向' }),
description: conv({ hans: '需要独立条目的页面', hant: '需要獨立條目的頁面' }),
subgroup: [
{
name: 'reqArticleLang',
type: 'input',
label: '外語語言代碼:',
tooltip: '使用ISO 639代碼,可參見 Template:ISO_639_name'
},
{
name: 'reqArticleTitle',
type: 'input',
label: '外語頁面名稱:',
size: 60
}
]
},
{ tag: conv({ hans: '快捷方式重定向', hant: '捷徑重定向' }), description: conv({ hans: '维基百科快捷方式', hant: '維基百科快捷方式' }) }
]
},
{
key: conv({ hans: '鲜用模板', hant: '鮮用模板' }),
value: [
{ tag: conv({ hans: '词组重定向', hant: '詞組重定向' }), description: conv({ hans: '将词组/词组/成语指向切题的条目及恰当章节', hant: '將詞組/詞組/成語指向切題的條目及恰當章節' }) },
{ tag: conv({ hans: '消歧义页重定向', hant: '消歧義頁重定向' }), description: conv({ hans: '指向消歧义页', hant: '指向消歧義頁' }) },
{ tag: '域名重定向', description: conv({ hans: '域名', hant: '網域名稱' }) },
{ tag: '年代重定向', description: conv({ hans: '于年份条目导向至年代条目', hant: '於年份條目導向至年代條目' }) },
{ tag: conv({ hans: '用户框模板重定向', hant: '用戶框模板重定向' }), description: conv({ hans: '用户框模板', hant: '用戶框模板' }) },
{ tag: '重定向模板用重定向', description: conv({ hans: '导向至重定向模板', hant: '導向至重定向模板' }) },
{ tag: 'EXIF重定向', description: conv({ hans: 'JPEG图像文件包含EXIF信息', hant: 'JPEG圖檔包含EXIF資訊' }) }
]
}];
// maintenance tags for FILES start here
Twinkle.tag.fileList = [{
key: conv({ hans: '著作权和来源问题标签', hant: '著作權和來源問題標籤' }),
value: [
{
label: '{{Non-free reduce}}:' + conv({ hans: '非低分辨率的合理使用图像(或过长的音频剪辑等)', hant: '非低解析度的合理使用圖像(或過長的音頻剪輯等)' }), value: 'Non-free reduce'
}
]
},
{
key: conv({ hans: '维基共享资源相关标签', hant: '維基共享資源相關標籤' }),
value: [
{
label: '{{Copy to Wikimedia Commons}}:' + conv({ hans: '自由著作权文件应该被移动至维基共享资源', hant: '自由版權檔案應該被移動至維基共享資源' }), value: 'Copy to Wikimedia Commons'
},
{
label: '{{Do not move to Commons}}:' + conv({ hans: '不要移动至维基共享资源', hant: '不要移動至維基共享資源' }),
value: 'Do not move to Commons',
subgroup: {
type: 'input',
name: 'DoNotMoveToCommons_reason',
label: '原因:',
tooltip: conv({ hans: '输入不应该将该图像移动到维基共享资源的原因(必填)。', hant: '輸入不應該將該圖像移動到維基共享資源的原因(必填)。' })
}
},
{
label: '{{Keep local}}:' + conv({ hans: '请求在本地保留维基共享资源的文件副本', hant: '請求在本地保留維基共享資源的檔案副本' }),
value: 'Keep local',
subgroup: [
{
type: 'input',
name: 'keeplocalName',
label: conv({ hans: '共享资源的不同图像名称:', hant: '共享資源的不同圖像名稱:' }),
tooltip: conv({ hans: '输入在共享资源的图像名称(如果不同于本地名称),不包括 File: 前缀', hant: '輸入在共享資源的圖像名稱(如果不同於本地名稱),不包括 File: 字首' })
},
{
type: 'input',
name: 'keeplocalReason',
label: '原因:',
tooltip: conv({ hans: '输入请求在本地保留文件副本的原因(可选):', hant: '輸入請求在本地保留檔案副本的原因(可選):' })
}
]
},
{
label: '{{Now Commons}}:' + conv({ hans: '文件已被复制到维基共享资源(CSD F7)', hant: '檔案已被複製到維基共享資源(CSD F7)' }),
value: 'Now Commons',
subgroup: {
type: 'input',
name: 'nowcommonsName',
label: conv({ hans: '共享资源的不同图像名称:', hant: '共享資源的不同圖像名稱:' }),
tooltip: conv({ hans: '输入在共享资源的图像名称(如果不同于本地名称),不包括 File: 前缀', hant: '輸入在共享資源的圖像名稱(如果不同於本地名稱),不包括 File: 字首' })
}
}
]
},
{
key: conv({ hans: '清理标签', hant: '清理標籤' }),
value: [
{ label: '{{Watermark}}:' + conv({ hans: '图像包含了水印', hant: '圖像包含了浮水印' }), value: 'Watermark' },
{
label: '{{Rename media}}:' + conv({ hans: '文件应该根据文件名称指引被重命名', hant: '檔案應該根據檔案名稱指引被重新命名' }),
value: 'Rename media',
subgroup: [
{
type: 'input',
name: 'renamemediaNewname',
label: conv({ hans: '新名称:', hant: '新名稱:' }),
tooltip: conv({ hans: '输入图像的新名称(可选)', hant: '輸入圖像的新名稱(可選)' })
},
{
type: 'input',
name: 'renamemediaReason',
label: '原因:',
tooltip: conv({ hans: '输入重命名的原因(可选)', hant: '輸入重新命名的原因(可選)' })
}
]
},
{ label: '{{Should be SVG}}:' + conv({ hans: 'PNG、GIF、JPEG文件应该重制成矢量图形', hant: 'PNG、GIF、JPEG檔案應該重製成向量圖形' }), value: 'Should be SVG' }
]
},
{
key: conv({ hans: '文件取代标签', hant: '檔案取代標籤' }),
value: [
{ label: '{{Obsolete}}:' + conv({ hans: '有新版本可用的过时文件', hant: '有新版本可用的過時檔案' }), value: 'Obsolete' },
{ label: '{{Vector version available}}:' + conv({ hans: '有矢量图形可用的非矢量图形文件', hant: '有向量圖形可用的非向量圖形檔案' }), value: 'Vector version available' }
],
buildFilename: true
}];
Twinkle.tag.callbacks = {
article: function articleCallback(pageobj) {
// Remove tags that become superfluous with this action
var pageText = pageobj.getPageText().replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
var params = pageobj.getCallbackParameters();
/**
* Saves the page following the removal of tags if any. The last step.
* Called from removeTags()
*/
var postRemoval = function() {
if (params.tagsToRemove.length) {
// Remove empty {{multiple issues}} if found
pageText = pageText.replace(/\{\{(multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|\s*\}\}\n?/im, '');
// Remove single-element {{multiple issues}} if found
pageText = pageText.replace(/\{\{(?:multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|\s*(\{\{(?:\{\{[^{}]*\}\}|[^{}])+\}\})\s*\}\}/im, '$1');
}
// Build edit summary
var makeSentence = function(array) {
if (array.length < 3) {
return array.join('和');
}
var last = array.pop();
return array.join('、') + '和' + last;
};
var makeTemplateLink = function(tag) {
var text = '{{[[';
// if it is a custom tag with a parameter
if (tag.indexOf('|') !== -1) {
tag = tag.slice(0, tag.indexOf('|'));
}
text += tag.indexOf(':') !== -1 ? tag : 'Template:' + tag + '|' + tag;
return text + ']]}}';
};
var summaryText;
var addedTags = params.tags.map(makeTemplateLink);
var removedTags = params.tagsToRemove.map(makeTemplateLink);
if (addedTags.length) {
summaryText = '加入' + makeSentence(addedTags);
summaryText += removedTags.length ? '並移除' + makeSentence(removedTags) : '';
} else {
summaryText = '移除' + makeSentence(removedTags);
}
summaryText += conv({ hans: '标记', hant: '標記' });
if (params.reason) {
summaryText += ':' + params.reason;
}
// avoid truncated summaries
if (summaryText.length > 499) {
summaryText = summaryText.replace(/\[\[[^|]+\|([^\]]+)\]\]/g, '$1');
}
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save(function() {
// special functions for merge tags
if (params.mergeReason) {
// post the rationale on the talk page (only operates in main namespace)
var talkpage = new Morebits.wiki.page('Talk:' + params.discussArticle, conv({ hans: '将理由贴进讨论页', hant: '將理由貼進討論頁' }));
talkpage.setNewSectionText(params.mergeReason.trim() + ' ~~~~');
talkpage.setNewSectionTitle('请求与[[' + params.nonDiscussArticle + ']]合并');
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setWatchlist(Twinkle.getPref('watchMergeDiscussions'));
talkpage.setCreateOption('recreate');
talkpage.newSection();
}
if (params.mergeTagOther) {
// tag the target page if requested
var otherTagName = 'Merge';
if (params.mergeTag === 'Merge from') {
otherTagName = 'Merge to';
} else if (params.mergeTag === 'Merge to') {
otherTagName = 'Merge from';
}
var newParams = {
tags: [otherTagName],
tagsToRemove: [],
tagsToRemain: [],
mergeTarget: Morebits.pageNameNorm,
discussArticle: params.discussArticle,
talkDiscussionTitle: params.talkDiscussionTitle,
talkDiscussionTitleLinked: params.talkDiscussionTitleLinked
};
var otherpage = new Morebits.wiki.page(params.mergeTarget, conv({ hans: '标记其他页面(', hant: '標記其他頁面(' }) +
params.mergeTarget + ')');
otherpage.setCallbackParameters(newParams);
otherpage.load(Twinkle.tag.callbacks.article);
}
// special functions for requested move tags
if (params.moveReason) {
// post the rationale on the talk page (only operates in main namespace)
var moveTalkpageText = '\n\n{{subst:RM|1=' + params.moveReason.trim();
if (params.moveTarget) {
moveTalkpageText += '|2=' + params.moveTarget;
}
moveTalkpageText += '}}';
var moveTalkpage = new Morebits.wiki.page('Talk:' + params.discussArticle, conv({ hans: '将理由贴进讨论页', hant: '將理由貼進討論頁' }));
moveTalkpage.setAppendText(moveTalkpageText);
moveTalkpage.setEditSummary(conv({ hans: '请求移动', hant: '請求移動' }) + (params.moveTarget ? '至[[' + params.moveTarget + ']]' : ''));
moveTalkpage.setChangeTags(Twinkle.changeTags);
moveTalkpage.setCreateOption('recreate');
moveTalkpage.append();
}
});
if (params.patrol) {
pageobj.patrol();
}
};
/**
* Removes the existing tags that were deselected (if any)
* Calls postRemoval() when done
*/
var removeTags = function removeTags() {
if (params.tagsToRemove.length === 0) {
postRemoval();
return;
}
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '移除取消选择的已存在标记', hant: '移除取消選擇的已存在標記' }));
var getRedirectsFor = [];
// Remove the tags from the page text, if found in its proper name,
// otherwise moves it to `getRedirectsFor` array earmarking it for
// later removal
params.tagsToRemove.forEach(function removeTag(tag) {
var tag_re = new RegExp('\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]+)?\\}\\}\\n?');
if (tag_re.test(pageText)) {
pageText = pageText.replace(tag_re, '');
} else {
getRedirectsFor.push('Template:' + tag);
}
});
if (!getRedirectsFor.length) {
postRemoval();
return;
}
// Remove tags which appear in page text as redirects
var api = new Morebits.wiki.api(conv({ hans: '获取模板重定向', hant: '取得模板重新導向' }), {
action: 'query',
prop: 'linkshere',
titles: getRedirectsFor.join('|'),
redirects: 1, // follow redirect if the class name turns out to be a redirect page
lhnamespace: '10', // template namespace only
lhshow: 'redirect',
lhlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
}, function removeRedirectTag(apiobj) {
$(apiobj.responseXML).find('page').each(function(idx, page) {
var removed = false;
$(page).find('lh').each(function(idx, el) {
var tag = $(el).attr('title').slice(9);
var tag_re = new RegExp('\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?\\}\\}\\n?');
if (tag_re.test(pageText)) {
pageText = pageText.replace(tag_re, '');
removed = true;
return false; // break out of $.each
}
});
if (!removed) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法在页面上找到{{', hant: '無法在頁面上找到{{' }) + $(page).attr('title').slice(9) + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
});
postRemoval();
});
api.post();
};
if (!params.tags.length) {
removeTags();
return;
}
var tagRe, tagText = '', tags = [], groupableTags = [], groupableExistingTags = [];
// Executes first: addition of selected tags
/**
* Updates `tagText` with the syntax of `tagName` template with its parameters
* @param {number} tagIndex
* @param {string} tagName
*/
var addTag = function articleAddTag(tagIndex, tagName) {
var currentTag = '';
if (tagName === 'Uncategorized' || tagName === 'Improve categories') {
pageText += '\n\n{{' + tagName + '|time={{subst:#time:c}}}}';
} else {
currentTag += '{{' + tagName;
// fill in other parameters, based on the tag
switch (tagName) {
case 'Expand language':
currentTag += '|1=' + params.expandLanguage;
if (params.highQualityArticle) {
currentTag += '|status=yes';
}
if (params.expandLanguage2) {
currentTag += '|2=' + params.expandLanguage2;
if (params.highQualityArticle2) {
currentTag += '|status2=yes';
}
}
if (params.expandLanguage3) {
currentTag += '|3=' + params.expandLanguage3;
if (params.highQualityArticle3) {
currentTag += '|status3=yes';
}
}
break;
case 'Expert needed':
currentTag += '|subject=' + params.expert;
if (params.expert2) {
currentTag += '|subject2=' + params.expert2;
}
if (params.expert3) {
currentTag += '|subject3=' + params.expert3;
}
break;
case 'Merge':
case 'Merge to':
case 'Merge from':
if (params.mergeTarget) {
// normalize the merge target for now and later
params.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.mergeTarget.replace(/_/g, ' '));
currentTag += '|' + params.mergeTarget;
// link to the correct section on the talk page, for article space only
if (mw.config.get('wgNamespaceNumber') === 0 && (params.mergeReason || params.discussArticle)) {
if (!params.discussArticle) {
// discussArticle is the article whose talk page will contain the discussion
params.discussArticle = tagName === 'Merge to' ? params.mergeTarget : mw.config.get('wgTitle');
// nonDiscussArticle is the article which won't have the discussion
params.nonDiscussArticle = tagName === 'Merge to' ? mw.config.get('wgTitle') : params.mergeTarget;
params.talkDiscussionTitle = conv({ hans: '请求与', hant: '請求與' }) + params.nonDiscussArticle + conv({ hans: '合并', hant: '合併' });
}
currentTag += '|discuss=Talk:' + params.discussArticle + '#' + params.talkDiscussionTitle;
}
}
break;
case 'Missing information':
currentTag += '|1=' + params.missingInformation;
break;
case 'Notability':
if (params.notability !== 'none') {
currentTag += '|3=' + params.notability;
}
break;
case 'Requested move':
if (params.moveTarget) {
// normalize the move target for now and later
params.moveTarget = Morebits.string.toUpperCaseFirstChar(params.moveTarget.replace(/_/g, ' '));
params.discussArticle = mw.config.get('wgTitle');
currentTag += '|' + params.moveTarget;
}
break;
case 'Split':
if (params.target1) {
currentTag += '|1=' + params.target1;
}
if (params.target2) {
currentTag += '|2=' + params.target2;
}
if (params.target3) {
currentTag += '|3=' + params.target3;
}
break;
case 'Cleanup':
if (params.cleanupReason) {
currentTag += '|reason=' + params.cleanupReason;
}
break;
default:
break;
}
currentTag += '|time={{subst:#time:c}}}}\n';
tagText += currentTag;
}
};
/**
* Adds the tags which go outside {{multiple issues}}, either because
* these tags aren't supported in {{multiple issues}} or because
* {{multiple issues}} is not being added to the page at all
*/
var addUngroupedTags = function() {
$.each(tags, addTag);
// Insert tag after short description or any hatnotes,
// as well as deletion/protection-related templates
var wikipage = new Morebits.wikitext.page(pageText);
var templatesAfter = Twinkle.hatnoteRegex +
// Protection templates
'pp|pp-.*?|' +
// CSD
'(?:Delete|Db-reason|D|Deletebecause|Db|速删|速刪|Speedy|SD|快删|快刪|CSD)|' +
// AfD
'[rsaiftcmv]fd|vfd-(?:b|q|s|source|v|wikt)|(?:移动到维基|移動到維基)(?:教科书|教科書|语录|語錄|文库|文庫|导游|導遊|词典|詞典)';
pageText = wikipage.insertAfterTemplates(tagText, templatesAfter).getText();
removeTags();
};
// Separate tags into groupable ones (`groupableTags`) and non-groupable ones (`tags`)
params.tags.forEach(function(tag) {
tagRe = new RegExp('\\{\\{' + tag + '(\\||\\}\\})', 'im');
// regex check for preexistence of tag can be skipped if in canRemove mode
if (Twinkle.tag.canRemove || !tagRe.exec(pageText)) {
if (tag === 'Notability' && (mw.config.get('wgNamespaceNumber') === 0 || confirm(conv({ hans: '该页面不是条目,您仍要提报到关注度提报吗?', hant: '該頁面不是條目,您仍要提報到關注度提報嗎?' })))) {
var wikipedia_page = new Morebits.wiki.page('Wikipedia:关注度/提报', conv({ hans: '加入关注度记录项', hant: '加入關注度記錄項' }));
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.tag.callbacks.notabilityList);
}
// condition Twinkle.tag.article.tags[tag] to ensure that its not a custom tag
// Custom tags are assumed non-groupable, since we don't know whether MI template supports them
if (Twinkle.tag.article.flatObject[tag] && !Twinkle.tag.article.flatObject[tag].excludeMI) {
groupableTags.push(tag);
} else {
tags.push(tag);
}
} else {
if (tag === 'Merge from') {
tags.push(tag);
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '在页面上找到{{', hant: '在頁面上找到{{' }) + tag + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
// don't do anything else with merge tags
if (['Merge', 'Merge to'].indexOf(tag) !== -1) {
params.mergeTarget = params.mergeReason = params.mergeTagOther = null;
}
}
}
});
// To-be-retained existing tags that are groupable
params.tagsToRemain.forEach(function(tag) {
// If the tag is unknown to us, we consider it non-groupable
if (Twinkle.tag.article.flatObject[tag] && !Twinkle.tag.article.flatObject[tag].excludeMI) {
groupableExistingTags.push(tag);
}
});
var miTest = /\{\{(multiple ?issues|article ?issues|mi|ai|issues|多個問題|多个问题|問題條目|问题条目|數個問題|数个问题)\s*\|[^}]+\{/im.exec(pageText);
if (miTest && groupableTags.length > 0) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入支持的标记入已存在的{{multiple issues}}', hant: '加入支援的標記入已存在的{{multiple issues}}' }));
tagText = '';
$.each(groupableTags, addTag);
var miRegex = new RegExp('(\\{\\{\\s*' + miTest[1] + '\\s*(?:\\|(?:\\{\\{[^{}]*\\}\\}|[^{}])*)?)\\}\\}\\s*', 'im');
pageText = pageText.replace(miRegex, '$1' + tagText + '}}\n');
tagText = '';
addUngroupedTags();
} else if (params.group && !miTest && (groupableExistingTags.length + groupableTags.length) >= 2) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '加入支持的标记入{{multiple issues}}', hant: '加入支援的標記入{{multiple issues}}' }));
tagText += '{{Multiple issues|\n';
/**
* Adds newly added tags to MI
*/
var addNewTagsToMI = function() {
$.each(groupableTags, addTag);
tagText += '}}\n';
addUngroupedTags();
};
var getRedirectsFor = [];
// Reposition the tags on the page into {{multiple issues}}, if found with its
// proper name, else moves it to `getRedirectsFor` array to be handled later
groupableExistingTags.forEach(function repositionTagIntoMI(tag) {
var tag_re = new RegExp('(\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]+)?\\}\\}\\n?)');
if (tag_re.test(pageText)) {
tagText += tag_re.exec(pageText)[1];
pageText = pageText.replace(tag_re, '');
} else {
getRedirectsFor.push('Template:' + tag);
}
});
if (!getRedirectsFor.length) {
addNewTagsToMI();
return;
}
var api = new Morebits.wiki.api(conv({ hans: '获取模板重定向', hant: '取得模板重新導向' }), {
action: 'query',
prop: 'linkshere',
titles: getRedirectsFor.join('|'),
redirects: 1,
lhnamespace: '10', // template namespace only
lhshow: 'redirect',
lhlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
}, function replaceRedirectTag(apiobj) {
$(apiobj.responseXML).find('page').each(function(idx, page) {
var found = false;
$(page).find('lh').each(function(idx, el) {
var tag = $(el).attr('title').slice(9);
var tag_re = new RegExp('(\\{\\{' + Morebits.pageNameRegex(tag) + '\\s*(\\|[^}]*)?\\}\\}\\n?)');
if (tag_re.test(pageText)) {
tagText += tag_re.exec(pageText)[1];
pageText = pageText.replace(tag_re, '');
found = true;
return false; // break out of $.each
}
});
if (!found) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法在页面上找到{{', hant: '無法在頁面上找到{{' }) + $(page).attr('title').slice(9) + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
});
addNewTagsToMI();
});
api.post();
} else {
tags = tags.concat(groupableTags);
addUngroupedTags();
}
},
notabilityList: function(pageobj) {
// var text = pageobj.getPageText();
// var params = pageobj.getCallbackParameters();
pageobj.setAppendText('\n{{subst:Fameitem|title=' + Morebits.pageNameNorm + '}}');
pageobj.setEditSummary('加入' + '[[' + Morebits.pageNameNorm + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
},
redirect: function redirect(pageobj) {
var params = pageobj.getCallbackParameters(),
pageText = pageobj.getPageText(),
tagRe, tagText = '', summaryText = '加入',
tags = [], i;
for (i = 0; i < params.tags.length; i++) {
tagRe = new RegExp('(\\{\\{' + params.tags[i] + '(\\||\\}\\}))', 'im');
if (!tagRe.exec(pageText)) {
tags.push(params.tags[i]);
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '在重定向上找到{{', hant: '在重新導向上找到{{' }) + params.tags[i] + conv({ hans: '}}…跳过', hant: '}}…跳過' }));
}
}
var addTag = function redirectAddTag(tagIndex, tagName) {
tagText += '\n{{' + tagName;
if (tagName === '非中文重定向') {
if (params.altLangFrom) {
tagText += '|1=' + params.altLangFrom;
}
} else if (tagName === '条目请求重定向' || tagName === '條目請求重定向') {
if (params.reqArticleLang && params.reqArticleTitle) {
tagText += '|1=' + params.reqArticleLang;
tagText += '|2=' + params.reqArticleTitle;
}
}
tagText += '}}';
if (tagIndex > 0) {
if (tagIndex === (tags.length - 1)) {
summaryText += '和';
} else if (tagIndex < (tags.length - 1)) {
summaryText += '、';
}
}
summaryText += '{{[[:' + (tagName.indexOf(':') !== -1 ? tagName : 'Template:' + tagName + '|' + tagName) + ']]}}';
};
if (!tags.length) {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '没有标签可供标记', hant: '沒有標籤可供標記' }));
}
tags.sort();
$.each(tags, addTag);
// Check for all Rcat shell redirects (from #433)
if (pageText.match(/{{(?:redr|this is a redirect|r(?:edirect)?(?:.?cat.*)?[ _]?sh)/i)) {
// Regex inspired by [[User:Kephir/gadgets/sagittarius.js]] ([[Special:PermaLink/831402893]])
var oldTags = pageText.match(/(\s*{{[A-Za-z\s]+\|(?:\s*1=)?)((?:[^|{}]|{{[^}]+}})+)(}})\s*/i);
pageText = pageText.replace(oldTags[0], oldTags[1] + tagText + oldTags[2] + oldTags[3]);
} else {
// Fold any pre-existing Rcats into taglist and under Rcatshell
var pageTags = pageText.match(/\s*{{.+?重定向.*?}}/img);
var oldPageTags = '';
if (pageTags) {
pageTags.forEach(function(pageTag) {
var pageRe = new RegExp(Morebits.string.escapeRegExp(pageTag), 'img');
pageText = pageText.replace(pageRe, '');
pageTag = pageTag.trim();
oldPageTags += '\n' + pageTag;
});
}
pageText += '\n{{Redirect category shell|' + tagText + oldPageTags + '\n}}';
}
summaryText += (tags.length > 0 ? conv({ hans: '标记', hant: '標記' }) : '{{Redirect category shell}}') + conv({ hans: '到重定向', hant: '到重新導向' });
// avoid truncated summaries
if (summaryText.length > 499) {
summaryText = summaryText.replace(/\[\[[^|]+\|([^\]]+)\]\]/g, '$1');
}
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
},
file: function friendlytagCallbacksFile(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var summary = '加入';
// Add maintenance tags
if (params.tags.length) {
var tagtext = '', currentTag;
$.each(params.tags, function(k, tag) {
// when other commons-related tags are placed, remove "move to Commons" tag
if (['Keep local', 'Now Commons', 'Do not move to Commons'].indexOf(tag) !== -1) {
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
if (tag === 'Vector version available') {
text = text.replace(/\{\{((convert to |convertto|should be |shouldbe|to)?svg|badpng|vectorize)[^}]*\}\}/gi, '');
}
currentTag = tag;
switch (tag) {
case 'Now Commons':
currentTag = 'subst:' + currentTag; // subst
if (params.nowcommonsName !== '') {
currentTag += '|1=' + params.nowcommonsName;
}
break;
case 'Keep local':
if (params.keeplocalName !== '') {
currentTag += '|1=' + params.keeplocalName;
}
if (params.keeplocalReason !== '') {
currentTag += '|reason=' + params.keeplocalReason;
}
break;
case 'Rename media':
if (params.renamemediaNewname !== '') {
currentTag += '|1=' + params.renamemediaNewname;
}
if (params.renamemediaReason !== '') {
currentTag += '|2=' + params.renamemediaReason;
}
break;
case 'Vector version available':
/* falls through */
case 'Obsolete':
currentTag += '|1=' + params[tag.replace(/ /g, '_') + 'File'];
break;
case 'Do not move to Commons':
currentTag += '|reason=' + params.DoNotMoveToCommons_reason;
break;
case 'Copy to Wikimedia Commons':
currentTag += '|human=' + mw.config.get('wgUserName');
break;
default:
break; // don't care
}
currentTag = '{{' + currentTag + '}}\n';
tagtext += currentTag;
summary += '{{' + tag + '}}、';
});
if (!tagtext) {
pageobj.getStatusElement().warn(conv({ hans: '用户取消操作,没什么要做的', hant: '使用者取消操作,沒什麼要做的' }));
return;
}
text = tagtext + text;
}
pageobj.setPageText(text);
pageobj.setEditSummary(summary.substring(0, summary.length - 1));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchTaggedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markTaggedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
}
};
Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
var form = e.target;
var params = Morebits.quickForm.getInputData(form);
// Validation
// Given an array of incompatible tags, check if we have two or more selected
var checkIncompatible = function(conflicts, extra) {
var count = conflicts.reduce(function(sum, tag) {
return sum += params.tags.indexOf(tag) !== -1;
}, 0);
if (count > 1) {
var message = conv({ hans: '请在以下标签中择一使用', hant: '請在以下標籤中擇一使用' }) + ':{{' + conflicts.join('}}、{{') + '}}。';
message += extra ? extra : '';
alert(message);
return true;
}
};
// Given a tag, ensure an associate parameter is present
// Maybe just sock this away in each function???
var checkParameter = function(tag, parameter, description) {
description = description || '理由';
if (params.tags.indexOf(tag) !== -1 && params[parameter].trim() === '') {
alert(conv({ hans: '您必须指定', hant: '您必須指定' }) + '{{' + tag + '}}的' + description + '。');
return true;
}
};
// We could theoretically put them all checkIncompatible calls in a
// forEach loop, but it's probably clearer not to have [[array one],
// [array two]] devoid of context. Likewise, all the checkParameter
// calls could be in one if, but could be similarly confusing.
switch (Twinkle.tag.modeEn) {
case 'article':
params.tagsToRemove = form.getUnchecked('existingTags'); // not in `input`
params.tagsToRemain = params.existingTags || []; // container not created if none present
if ((params.tags.indexOf('Merge') !== -1) || (params.tags.indexOf('Merge from') !== -1) ||
(params.tags.indexOf('Merge to') !== -1)) {
if (checkIncompatible(['Merge', 'Merge from', 'Merge to'], conv({ hans: '如果需要多次合并,请使用{{Merge}}并用管道符分隔条目名(但在这种情形中Twinkle不能自动标记其他条目)。', hant: '如果需要多次合併,請使用{{Merge}}並用管道符分隔條目名(但在這種情形中Twinkle不能自動標記其他條目)。' }))) {
return;
}
if (!params.mergeTarget) {
alert(conv({ hans: '请指定使用于merge模板中的另一个页面标题。', hant: '請指定使用於merge模板中的另一個頁面標題。' }));
return;
}
if ((params.mergeTagOther || params.mergeReason) && params.mergeTarget.indexOf('|') !== -1) {
alert(conv({ hans: '当前还不支持在一次合并中标记多个条目,与开启关于多个条目的讨论。请不要勾选“标记其他条目”并清空“理由”框后再提交。', hant: '目前還不支援在一次合併中標記多個條目,與開啟關於多個條目的討論。請不要勾選「標記其他條目」並清空「理由」框後再提交。' }));
return;
}
}
if (checkParameter('Expand language', 'expandLanguage', conv({ hans: '语言代码', hant: '語言代碼' }))) {
return;
}
if (checkParameter('Missing information', 'missingInformation', conv({ hans: '缺少的内容', hant: '缺少的內容' }))) {
return;
}
if (checkParameter('Expert needed', 'expert', conv({ hans: '专家领域', hant: '專家領域' }))) {
return;
}
break;
case 'file':
// Silly to provide the same string to each of these
if (checkParameter('Obsolete', 'ObsoleteFile', conv({ hans: '替换的文件名称', hant: '替換的檔案名稱' })) ||
checkParameter('Vector version available', 'Vector_version_availableFile', conv({ hans: '替换的文件名称', hant: '替換的檔案名稱' }))) {
return;
}
if (checkParameter('Do not move to Commons', 'DoNotMoveToCommons_reason')) {
return;
}
break;
case 'redirect':
break;
default:
alert('Twinkle.tag:未知模式 ' + Twinkle.tag.mode);
break;
}
// File/redirect: return if no tags selected
// Article: return if no tag is selected and no already present tag is deselected
if (params.tags.length === 0 && (Twinkle.tag.modeEn !== 'article' || params.tagsToRemove.length === 0)) {
alert(conv({ hans: '必须选择至少一个标记!', hant: '必須選擇至少一個標記!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = Morebits.pageNameNorm;
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成,将在几秒内刷新页面', hant: '標記完成,將在幾秒內重新整理頁面' });
if (Twinkle.tag.modeEn === 'redirect') {
Morebits.wiki.actionCompleted.followRedirect = false;
}
var wikipedia_page = new Morebits.wiki.page(Morebits.pageNameNorm, conv({ hans: '正在标记', hant: '正在標記' }) + Twinkle.tag.mode);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.tag.callbacks[Twinkle.tag.modeEn]);
};
Twinkle.addInitCallback(Twinkle.tag, 'tag');
})(jQuery);
// </nowiki>
c72718af4d8d95c5dac3dd4282fe12815ffb78e3
MediaWiki:Gadget-twinklestub.js
8
162
327
326
2024-08-03T04:07:26Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklestub.js: Tag module
****************************************
* Mode of invocation: Tab ("Stub")
* Active on: Existing articles
* Config directives in: FriendlyConfig
* Note: customised friendlytag module (for SEWP)
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.stub = function friendlytag() {
if (Morebits.isPageRedirect()) {
// Skip
// article/draft article tagging
} else if (((mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 118) && mw.config.get('wgCurRevisionId')) || (Morebits.pageNameNorm === Twinkle.getPref('sandboxPage'))) {
Twinkle.stub.mode = conv({ hans: '条目', hant: '條目' });
Twinkle.addPortletLink(Twinkle.stub.callback, '小作品', 'friendly-tag', conv({ hans: '标记小作品', hant: '標記小作品' }));
}
};
Twinkle.stub.callback = function friendlytagCallback() {
var Window = new Morebits.simpleWindow(630, Twinkle.stub.mode === 'article' ? 450 : 400);
Window.setScriptName('Twinkle');
Window.addFooterLink('小作品說明', 'Wikipedia:小作品');
Window.addFooterLink(conv({ hans: '小作品设置', hant: '小作品設定' }), 'WP:TW/PREF#stub');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#stub');
var form = new Morebits.quickForm(Twinkle.stub.callback.evaluate);
if (document.getElementsByClassName('patrollink').length) {
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '标记页面为已巡查', hant: '標記頁面為已巡查' }),
value: 'patrolPage',
name: 'patrolPage',
checked: Twinkle.getPref('markStubbedPagesAsPatrolled')
}
]
});
}
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
Window.setTitle(conv({ hans: '条目小作品标记', hant: '條目小作品標記' }));
form.append({
type: 'select',
name: 'sortorder',
label: conv({ hans: '查看列表:', hant: '檢視列表:' }),
tooltip: conv({ hans: '您可以在Twinkle参数设置(WP:TWPREFS)中更改此项。', hant: '您可以在Twinkle偏好設定(WP:TWPREFS)中更改此項。' }),
event: Twinkle.stub.updateSortOrder,
list: [
{ type: 'option', value: 'cat', label: conv({ hans: '按类型', hant: '按類別' }), selected: Twinkle.getPref('stubArticleSortOrder') === 'cat' },
{ type: 'option', value: 'alpha', label: '按字母', selected: Twinkle.getPref('stubArticleSortOrder') === 'alpha' }
]
});
form.append({ type: 'div', id: 'tagWorkArea' });
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
if (Twinkle.stub.mode === '条目' || Twinkle.stub.mode === '條目') {
// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sortorder.dispatchEvent(evt);
}
};
Twinkle.stub.checkedTags = [];
Twinkle.stub.updateSortOrder = function(e) {
var sortorder = e.target.value;
Twinkle.stub.checkedTags = e.target.form.getChecked('articleTags');
if (!Twinkle.stub.checkedTags) {
Twinkle.stub.checkedTags = [];
}
var container = new Morebits.quickForm.element({ type: 'fragment' });
// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: '{{' + tag + '}}: ' + description };
if (Twinkle.stub.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
return checkbox;
};
// append any custom tags
if (Twinkle.getPref('customStubList').length) {
container.append({ type: 'header', label: conv({ hans: '自定义模板', hant: '自訂模板' }) });
var customcheckboxes = [];
$.each(Twinkle.getPref('customStubList'), function(_, item) {
customcheckboxes.push(makeCheckbox(item.value, item.label));
});
container.append({
type: 'checkbox',
name: 'articleTags',
list: customcheckboxes
});
}
// categorical sort order
if (sortorder === 'cat') {
// function to iterate through the tags and create a checkbox for each one
var doCategoryCheckboxes = function(subdiv, array) {
var checkboxes = [];
$.each(array, function(k, tag) {
var description = Twinkle.stub.article.tags[tag];
checkboxes.push(makeCheckbox(tag, description));
});
subdiv.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
};
var i = 0;
// go through each category and sub-category and append lists of checkboxes
$.each(Twinkle.stub.article.tagCategories, function(title, content) {
container.append({ type: 'header', id: 'tagHeader' + i, label: title });
var subdiv = container.append({ type: 'div', id: 'tagSubdiv' + i++ });
if ($.isArray(content)) {
doCategoryCheckboxes(subdiv, content);
} else {
$.each(content, function(subtitle, subcontent) {
subdiv.append({ type: 'div', label: [Morebits.htmlNode('b', subtitle)] });
doCategoryCheckboxes(subdiv, subcontent);
});
}
});
// alphabetical sort order
} else {
var checkboxes = [];
$.each(Twinkle.stub.article.tags, function(tag, description) {
checkboxes.push(makeCheckbox(tag, description));
});
container.append({
type: 'checkbox',
name: 'articleTags',
list: checkboxes
});
}
var $workarea = $(e.target.form).find('div#tagWorkArea');
var rendered = container.render();
$workarea.empty().append(rendered);
// style adjustments
$workarea.find('h5').css({ 'font-size': '110%' });
$workarea.find('h5:not(:first-child)').css({ 'margin-top': '1em' });
$workarea.find('div').filter(':has(span.quickformDescription)').css({ 'margin-top': '0.4em' });
// add a link to each template's description page
$.each(Morebits.quickForm.getElements(e.target.form, 'articleTags'), function(index, checkbox) {
var $checkbox = $(checkbox);
var link = Morebits.htmlNode('a', '>');
link.setAttribute('class', 'tag-template-link');
link.setAttribute('href', mw.util.getUrl('Template:' +
Morebits.string.toUpperCaseFirstChar(checkbox.values)));
link.setAttribute('target', '_blank');
$checkbox.parent().append(['\u00A0', link]);
});
};
// Tags for ARTICLES start here
Twinkle.stub.article = {};
// A list of all article tags, in alphabetical order
// To ensure tags appear in the default "categorized" view, add them to the tagCategories hash below.
Twinkle.stub.article.tags = {
'actor-stub': conv({ hans: '演员', hant: '演員' }),
'asia-stub': conv({ hans: '亚洲', hant: '亞洲' }),
'bio-stub': conv({ hans: '人物', hant: '人物' }),
'biology-stub': conv({ hans: '生物学', hant: '生物學' }),
'chem-stub': conv({ hans: '化学', hant: '化學' }),
'europe-stub': conv({ hans: '欧洲', hant: '歐洲' }),
'expand list': conv({ hans: '未完成列表', hant: '未完成列表' }),
'food-stub': conv({ hans: '食物', hant: '食物' }),
'france-geo-stub': conv({ hans: '法国地理', hant: '法國地理' }),
'geo-stub': conv({ hans: '地理位置', hant: '地理位置' }),
'hist-stub': conv({ hans: '历史或历史学', hant: '歷史或歷史學' }),
'JP-stub': conv({ hans: '日本', hant: '日本' }),
'lit-stub': conv({ hans: '文学', hant: '文學' }),
'math-stub': conv({ hans: '数学', hant: '數學' }),
'med-stub': conv({ hans: '医学', hant: '醫學' }),
'mil-stub': conv({ hans: '军事', hant: '軍事' }),
'movie-stub': conv({ hans: '电影', hant: '電影' }),
'music-stub': conv({ hans: '音乐', hant: '音樂' }),
'physics-stub': conv({ hans: '物理学', hant: '物理學' }),
'politic-stub': conv({ hans: '政治', hant: '政治' }),
'religion-stub': conv({ hans: '宗教', hant: '宗教' }),
'science-stub': conv({ hans: '科学', hant: '科學' }),
'sport-stub': conv({ hans: '体育', hant: '體育' }),
'stub': conv({ hans: '通用小作品', hant: '通用小作品' }),
'switzerland-stub': conv({ hans: '瑞士', hant: '瑞士' }),
'tech-stub': conv({ hans: '科技', hant: '科技' }),
'transp-stub': conv({ hans: '交通', hant: '交通' }),
'TV-stub': conv({ hans: '电视', hant: '電視' }),
'UK-stub': conv({ hans: '英国', hant: '英國' }),
'US-bio-stub': conv({ hans: '美国人物', hant: '美國人物' }),
'US-geo-stub': conv({ hans: '美国地理', hant: '美國地理' }),
'US-stub': conv({ hans: '美国', hant: '美國' }),
'weather-stub': conv({ hans: '天气和特别的天气事件', hant: '天氣和特別的天氣事件' })
};
// A list of tags in order of category
// Tags should be in alphabetical order within the categories
// Add new categories with discretion - the list is long enough as is!
Twinkle.stub.article.tagCategories = {
[conv({ hans: '通用模板', hant: '通用模板' })]: [
'stub',
'expand list'
],
[conv({ hans: '国家和地理', hant: '國家和地理' })]: [
'asia-stub',
'europe-stub',
'france-geo-stub',
'geo-stub',
'JP-stub',
'switzerland-stub',
'UK-stub',
'US-bio-stub',
'US-geo-stub',
'US-stub'
],
[conv({ hans: '杂项', hant: '雜項' })]: [
'food-stub',
'hist-stub',
'mil-stub',
'politic-stub',
'religion-stub',
'transp-stub'
],
[conv({ hans: '人物', hant: '人物' })]: [
'actor-stub',
'bio-stub',
'US-bio-stub'
],
[conv({ hans: '科学', hant: '科學' })]: [
'biology-stub',
'chem-stub',
'math-stub',
'med-stub',
'physics-stub',
'science-stub',
'weather-stub'
],
[conv({ hans: '体育', hant: '體育' })]: [
'sport-stub'
],
[conv({ hans: '技术', hant: '技術' })]: [
'tech-stub'
],
[conv({ hans: '艺术', hant: '藝術' })]: [
'actor-stub',
'lit-stub',
'movie-stub',
'music-stub',
'TV-stub'
]
};
/* eslint-enable quote-props */
// Tags for REDIRECTS start here
Twinkle.stub.callbacks = {
main: function(pageobj) {
var params = pageobj.getCallbackParameters(),
tagRe, summaryText = '加入',
tags = [], groupableTags = [], i, totalTags;
// Remove tags that become superfluous with this action
var pageText = pageobj.getPageText();
var addTag = function friendlytagAddTag(tagIndex, tagName) {
pageText += '\n{{' + tagName + '}}';
if (tagIndex > 0) {
if (tagIndex === (totalTags - 1)) {
summaryText += '和';
} else if (tagIndex < (totalTags - 1)) {
summaryText += '、';
}
}
summaryText += '{{[[';
summaryText += tagName.indexOf(':') !== -1 ? tagName : 'Template:' + tagName + '|' + tagName;
summaryText += ']]}}';
};
// Check for preexisting tags and separate tags into groupable and non-groupable arrays
for (i = 0; i < params.tags.length; i++) {
tagRe = new RegExp('(\\{\\{' + params.tags[i] + '(\\||\\}\\}))', 'im');
if (!tagRe.exec(pageText)) {
tags = tags.concat(params.tags[i]);
} else {
Morebits.status.info(
conv({ hans: '信息', hant: '資訊' }),
conv({
hans: '在页面上找到{{' + params.tags[i] + '}}…跳过',
hant: '在頁面上找到{{' + params.tags[i] + '}}…跳過'
}));
}
}
tags = tags.concat(groupableTags);
tags.sort();
totalTags = tags.length;
$.each(tags, addTag);
summaryText += conv({ hans: '标记到', hant: '標記到' }) + Twinkle.stub.mode;
pageobj.setPageText(pageText);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchStubbedPages'));
pageobj.setMinorEdit(Twinkle.getPref('markStubbedPagesAsMinor'));
pageobj.setCreateOption('nocreate');
pageobj.save();
if (params.patrol) {
pageobj.patrol();
}
}
};
Twinkle.stub.callback.evaluate = function friendlytagCallbackEvaluate(e) {
var form = e.target;
var params = {};
if (form.patrolPage) {
params.patrol = form.patrolPage.checked;
}
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
params.tags = form.getChecked('articleTags');
params.group = false;
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
if (!params.tags.length) {
alert(conv({ hans: '必须选择至少一个标记!', hant: '必須選擇至少一個標記!' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = conv({ hans: '标记完成,将在几秒内刷新页面', hant: '標記完成,將在幾秒內重新整理頁面' });
if (Twinkle.stub.mode === '重定向') {
Morebits.wiki.actionCompleted.followRedirect = false;
}
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '正在标记', hant: '正在標記' }) + Twinkle.stub.mode);
wikipedia_page.setCallbackParameters(params);
switch (Twinkle.stub.mode) {
case '條目':
case '条目':
/* falls through */
case '重定向':
wikipedia_page.load(Twinkle.stub.callbacks.main);
return;
case '文件':
case '檔案':
wikipedia_page.load(Twinkle.stub.callbacks.file);
break;
default:
alert('Twinkle.stub:未知模式 ' + Twinkle.stub.mode);
break;
}
};
Twinkle.addInitCallback(Twinkle.stub, 'stub');
})(jQuery);
// </nowiki>
e50d97a516060cfc8907a60626c14210160dbfcd
MediaWiki:Gadget-twinklediff.js
8
163
329
328
2024-08-03T04:07:27Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklediff.js: Diff module
****************************************
* Mode of invocation: Tab on non-diff pages ("Last"); tabs on diff pages ("Since", "Since mine", "Current")
* Active on: Existing non-special pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.diff = function twinklediff() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageContentModel') === 'flow-board' || !mw.config.get('wgArticleId')) {
return;
}
Twinkle.addPortletLink(mw.util.getUrl(mw.config.get('wgPageName'), { diff: 'cur', oldid: 'prev' }), conv({ hans: '最后', hant: '最後' }), 'tw-lastdiff', conv({ hans: '显示最后修改', hant: '顯示最後修改' }));
// Show additional tabs only on diff pages
if (mw.config.get('wgDiffNewId')) {
Twinkle.addPortletLink(function() {
Twinkle.diff.evaluate(false);
}, '自上', 'tw-since', conv({ hans: '显示与上一修订版本间的差异', hant: '顯示與上一修訂版本間的差異' }));
Twinkle.addPortletLink(function() {
Twinkle.diff.evaluate(true);
}, '自我', 'tw-sincemine', conv({ hans: '显示与我做出的修订版本的差异', hant: '顯示與我做出的修訂版本的差異' }));
Twinkle.addPortletLink(mw.util.getUrl(mw.config.get('wgPageName'), { diff: 'cur', oldid: mw.config.get('wgDiffNewId') }), conv({ hans: '当前', hant: '目前' }), 'tw-curdiff', conv({ hans: '显示与当前版本间的差异', hant: '顯示與目前版本間的差異' }));
}
};
Twinkle.diff.evaluate = function twinklediffEvaluate(me) {
var user;
if (me) {
user = mw.config.get('wgUserName');
} else {
var node = document.getElementById('mw-diff-ntitle2');
if (!node) {
// nothing to do?
return;
}
user = $(node).find('a').first().text();
}
var query = {
prop: 'revisions',
action: 'query',
titles: mw.config.get('wgPageName'),
rvlimit: 1,
rvprop: [ 'ids', 'user' ],
rvstartid: mw.config.get('wgCurRevisionId') - 1, // i.e. not the current one
rvuser: user
};
Morebits.status.init(document.getElementById('mw-content-text'));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取最初贡献者信息', hant: '抓取最初貢獻者資訊' }), query, Twinkle.diff.callbacks.main);
wikipedia_api.params = { user: user };
wikipedia_api.post();
};
Twinkle.diff.callbacks = {
main: function(self) {
var xmlDoc = self.responseXML;
var revid = $(xmlDoc).find('rev').attr('revid');
if (!revid) {
self.statelem.error(conv({ hans: '未找到合适的早期版本,或 ', hant: '未找到合適的早期版本,或 ' }) + self.params.user + conv({ hans: ' 是唯一贡献者。取消。', hant: ' 是唯一貢獻者。取消。' }));
return;
}
window.location = mw.util.getUrl(mw.config.get('wgPageName'), {
diff: mw.config.get('wgCurRevisionId'),
oldid: revid
});
}
};
Twinkle.addInitCallback(Twinkle.diff, 'diff');
})(jQuery);
// </nowiki>
67886f369cd2fca278e97a889516799a7e6e7ed2
MediaWiki:Gadget-twinkleunlink.js
8
164
331
330
2024-08-03T04:07:28Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleunlink.js: Unlink module
****************************************
* Mode of invocation: Tab ("Unlink")
* Active on: Non-special pages, except Wikipedia:Sandbox
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.unlink = function twinkleunlink() {
if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgPageName') === Twinkle.getPref('sandboxPage') || !Morebits.userIsSysop) {
return;
}
Twinkle.addPortletLink(Twinkle.unlink.callback, conv({ hans: '消链', hant: '消連' }), 'tw-unlink', conv({ hans: '取消到本页的链接', hant: '取消到本頁的連結' }));
};
// the parameter is used when invoking unlink from admin speedy
Twinkle.unlink.callback = function(presetReason) {
var fileSpace = mw.config.get('wgNamespaceNumber') === 6;
var Window = new Morebits.simpleWindow(600, 440);
Window.setTitle(conv({ hans: '取消链入', hant: '取消連入' }) + (fileSpace ? conv({ hans: '和文件使用', hant: '和檔案使用' }) : ''));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '链入设置', hant: '連入設定' }), 'WP:TW/PREF#unlink');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#unlink');
var form = new Morebits.quickForm(Twinkle.unlink.callback.evaluate);
// prepend some documentation: files are commented out, while any
// display text is preserved for links (otherwise the link itself is used)
var linkTextBefore = Morebits.htmlNode('code', '[[' + (fileSpace ? ':' : '') + Morebits.pageNameNorm + conv({ hans: '|链接文字]]', hant: '|連結文字]]' }));
var linkTextAfter = Morebits.htmlNode('code', conv({ hans: '链接文字', hant: '連結文字' }));
var linkPlainBefore = Morebits.htmlNode('code', '[[' + Morebits.pageNameNorm + ']]');
var linkPlainAfter;
if (fileSpace) {
linkPlainAfter = Morebits.htmlNode('code', '<!-- [[' + Morebits.pageNameNorm + ']] -->');
} else {
linkPlainAfter = Morebits.htmlNode('code', Morebits.pageNameNorm);
}
[linkTextBefore, linkTextAfter, linkPlainBefore, linkPlainAfter].forEach(function(node) {
node.style.fontFamily = 'monospace';
node.style.fontStyle = 'normal';
});
form.append({
type: 'div',
style: 'margin-bottom: 0.5em',
label: [
conv({ hans: '这个工具可以取消所有指向该页的链接(“链入”)', hant: '這個工具可以取消所有指向該頁的連結(「連入」)' }) +
(fileSpace ? conv({ hans: ',或通过加入<!-- -->注释标记隐藏所有对此文件的使用', hant: ',或透過加入<!-- -->注釋標記隱藏所有對此檔案的使用' }) : '') +
'。例如:',
linkTextBefore, conv({ hans: '将会变成', hant: '將會變成' }), linkTextAfter, ',',
linkPlainBefore, conv({ hans: '将会变成', hant: '將會變成' }), linkPlainAfter, conv({ hans: '。请小心使用。', hant: '。請小心使用。' })
]
});
form.append({
type: 'input',
name: 'reason',
label: '理由:',
value: presetReason ? presetReason : '',
size: 60
});
var query = {
action: 'query',
list: 'backlinks',
bltitle: mw.config.get('wgPageName'),
bllimit: 'max', // 500 is max for normal users, 5000 for bots and sysops
blnamespace: Twinkle.getPref('unlinkNamespaces'),
rawcontinue: true,
format: 'json'
};
if (fileSpace) {
query.list += '|imageusage';
query.iutitle = query.bltitle;
query.iulimit = query.bllimit;
query.iunamespace = query.blnamespace;
} else {
query.blfilterredir = 'nonredirects';
}
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取链入', hant: '抓取連入' }), query, Twinkle.unlink.callbacks.display.backlinks);
wikipedia_api.params = { form: form, Window: Window, image: fileSpace };
wikipedia_api.post();
var root = document.createElement('div');
root.style.padding = '15px'; // just so it doesn't look broken
Morebits.status.init(root);
wikipedia_api.statelem.status(conv({ hans: '加载中…', hant: '載入中…' }));
Window.setContent(root);
Window.display();
};
Twinkle.unlink.callback.evaluate = function twinkleunlinkCallbackEvaluate(event) {
var form = event.target;
var input = Morebits.quickForm.getInputData(form);
if (!input.reason) {
alert(conv({ hans: '您必须指定取消链入的理由。', hant: '您必須指定取消連入的理由。' }));
return;
}
input.backlinks = input.backlinks || [];
input.imageusage = input.imageusage || [];
var pages = Morebits.array.uniq(input.backlinks.concat(input.imageusage));
if (!pages.length) {
alert(conv({ hans: '您必须至少选择一个要取消链入的页面。', hant: '您必須至少選擇一個要取消連入的頁面。' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var unlinker = new Morebits.batchOperation('取消' + (input.backlinks.length ? conv({ hans: '链入', hant: '連入' }) +
(input.imageusage.length ? conv({ hans: '与文件使用', hant: '與檔案使用' }) : '') : conv({ hans: '文件使用', hant: '檔案使用' })));
unlinker.setOption('preserveIndividualStatusLines', true);
unlinker.setPageList(pages);
var params = { reason: input.reason, unlinker: unlinker };
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '在页面“', hant: '在頁面「' }) + pageName + conv({ hans: '”中取消链入', hant: '」中取消連入' }));
wikipedia_page.setBotEdit(true); // unlink considered a floody operation
wikipedia_page.setCallbackParameters($.extend({
doBacklinks: input.backlinks.indexOf(pageName) !== -1,
doImageusage: input.imageusage.indexOf(pageName) !== -1
}, params));
wikipedia_page.load(Twinkle.unlink.callbacks.unlinkBacklinks);
});
};
Twinkle.unlink.callbacks = {
display: {
backlinks: function twinkleunlinkCallbackDisplayBacklinks(apiobj) {
var response = apiobj.getResponse();
var havecontent = false;
var list, namespaces, i;
if (apiobj.params.image) {
var imageusage = response.query.imageusage.sort(Twinkle.sortByNamespace);
list = [];
for (i = 0; i < imageusage.length; ++i) {
// Label made by Twinkle.generateBatchPageLinks
list.push({ label: '', value: imageusage[i].title, checked: true });
}
if (!list.length) {
apiobj.params.form.append({ type: 'div', label: conv({ hans: '未找到文件使用。', hant: '未找到檔案使用。' }) });
} else {
apiobj.params.form.append({ type: 'header', label: conv({ hans: '文件使用', hant: '檔案使用' }) });
namespaces = [];
$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
namespaces.push(v === '0' ? conv({ hans: '(条目)', hant: '(條目)' }) : mw.config.get('wgFormattedNamespaces')[v]);
});
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '已选择的命名空间:', hant: '已選擇的命名空間:' }) + namespaces.join('、'),
tooltip: conv({ hans: '您可在Twinkle属性中更改这个,请参见[[WP:TWPREFS]]', hant: '您可在Twinkle屬性中更改這個,請參見[[WP:TWPREFS]]' })
});
if (response['query-continue'] && response['query-continue'].imageusage) {
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '显示前', hant: '顯示前' }) + mw.language.convertNumber(list.length) + conv({ hans: '个文件使用。', hant: '個檔案使用。' })
});
}
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'imageusage')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'imageusage')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'imageusage',
shiftClickSupport: true,
list: list
});
havecontent = true;
}
}
var backlinks = response.query.backlinks.sort(Twinkle.sortByNamespace);
if (backlinks.length > 0) {
list = [];
for (i = 0; i < backlinks.length; ++i) {
// Label made by Twinkle.generateBatchPageLinks
list.push({ label: '', value: backlinks[i].title, checked: true });
}
apiobj.params.form.append({ type: 'header', label: conv({ hans: '链入', hant: '連入' }) });
namespaces = [];
$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
namespaces.push(v === '0' ? conv({ hans: '(条目)', hant: '(條目)' }) : mw.config.get('wgFormattedNamespaces')[v]);
});
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '已选择的命名空间:', hant: '已選擇的命名空間:' }) + namespaces.join('、'),
tooltip: conv({ hans: '您可在Twinkle属性中更改这个,请参见[[WP:TWPREFS]]', hant: '您可在Twinkle屬性中更改這個,請參見[[WP:TWPREFS]]' })
});
if (response['query-continue'] && response['query-continue'].backlinks) {
apiobj.params.form.append({
type: 'div',
label: conv({ hans: '显示前', hant: '顯示前' }) + mw.language.convertNumber(list.length) + conv({ hans: '个链入。', hant: '個連入。' })
});
}
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'backlinks')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'backlinks')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'backlinks',
shiftClickSupport: true,
list: list
});
havecontent = true;
} else {
apiobj.params.form.append({ type: 'div', label: conv({ hans: '未找到链入。', hant: '未找到連入。' }) });
}
if (havecontent) {
apiobj.params.form.append({ type: 'submit' });
}
var result = apiobj.params.form.render();
apiobj.params.Window.setContent(result);
Morebits.quickForm.getElements(result, 'backlinks').forEach(Twinkle.generateBatchPageLinks);
Morebits.quickForm.getElements(result, 'imageusage').forEach(Twinkle.generateBatchPageLinks);
}
},
unlinkBacklinks: function twinkleunlinkCallbackUnlinkBacklinks(pageobj) {
var oldtext = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var wikiPage = new Morebits.wikitext.page(oldtext);
var summaryText = '', warningString = false;
var text;
// remove image usages
if (params.doImageusage) {
text = wikiPage.commentOutImage(mw.config.get('wgTitle'), conv({ hans: '注释', hant: '注釋' })).getText();
// did we actually make any changes?
if (text === oldtext) {
warningString = conv({ hans: '文件使用', hant: '檔案使用' });
} else {
summaryText = conv({ hans: '注释文件使用', hant: '注釋檔案使用' });
oldtext = text;
}
}
// remove backlinks
if (params.doBacklinks) {
text = wikiPage.removeLink(Morebits.pageNameNorm).getText();
// did we actually make any changes?
if (text === oldtext) {
warningString = warningString ? conv({ hans: '取消链入或文件使用', hant: '取消連入或檔案使用' }) : conv({ hans: '取消链入', hant: '取消連入' });
} else {
summaryText = (summaryText ? summaryText + ' / ' : '') + conv({ hans: '取消链结到', hant: '取消連結到' });
oldtext = text;
}
}
if (warningString) {
// nothing to do!
pageobj.getStatusElement().error(conv({ hans: '未能在页面上找到', hant: '未能在頁面上找到' }) + warningString + '。');
params.unlinker.workerFailure(pageobj);
return;
}
pageobj.setPageText(text);
pageobj.setEditSummary(summaryText + conv({ hans: '“', hant: '「' }) + Morebits.pageNameNorm + conv({ hans: '”:', hant: '」:' }) + params.reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
}
};
Twinkle.addInitCallback(Twinkle.unlink, 'unlink');
})(jQuery);
// </nowiki>
86b24bf86cc443470df944acfd46b80f310b8cc6
MediaWiki:Gadget-twinklefluff.js
8
165
333
332
2024-08-03T04:07:29Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklefluff.js: Revert/rollback module
****************************************
* Mode of invocation: Links on contributions, recent changes, history, and diff pages
* Active on: Diff pages, history pages, Special:RecentChanges(Linked),
and Special:Contributions
*/
/**
Twinklefluff revert and antivandalism utility
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.fluff = function twinklefluff() {
// Only proceed if the user can actually edit the page in question
// (see #632 for contribs issue). wgIsProbablyEditable should take
// care of namespace/contentModel restrictions as well as explicit
// protections; it won't take care of cascading or TitleBlacklist.
if (mw.config.get('wgIsProbablyEditable')) {
// wgDiffOldId included for clarity in if else loop [[phab:T214985]]
if (mw.config.get('wgDiffNewId') || mw.config.get('wgDiffOldId')) {
// Reload alongside the revision slider
mw.hook('wikipage.diff').add(function () {
Twinkle.fluff.addLinks.diff();
});
} else if (mw.config.get('wgAction') === 'view' && mw.config.get('wgRevisionId') && mw.config.get('wgCurRevisionId') !== mw.config.get('wgRevisionId')) {
Twinkle.fluff.addLinks.oldid();
} else if (mw.config.get('wgAction') === 'history') {
Twinkle.fluff.addLinks.history();
}
} else if (mw.config.get('wgNamespaceNumber') === -1) {
Twinkle.fluff.skipTalk = !Twinkle.getPref('openTalkPageOnAutoRevert');
Twinkle.fluff.rollbackInPlace = Twinkle.getPref('rollbackInPlace');
if (mw.config.get('wgCanonicalSpecialPageName') === 'Contributions') {
Twinkle.fluff.addLinks.contributions();
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'Recentchanges' || mw.config.get('wgCanonicalSpecialPageName') === 'Recentchangeslinked') {
// Reload with recent changes updates
// structuredChangeFilters.ui.initialized is just on load
mw.hook('wikipage.content').add(function(item) {
if (item.is('div')) {
Twinkle.fluff.addLinks.recentchanges();
}
});
}
}
};
// A list of usernames, usually only bots, that vandalism revert is jumped
// over; that is, if vandalism revert was chosen on such username, then its
// target is on the revision before. This is for handling quick bots that
// makes edits seconds after the original edit is made. This only affects
// vandalism rollback; for good faith rollback, it will stop, indicating a bot
// has no faith, and for normal rollback, it will rollback that edit.
Twinkle.fluff.trustedBots = [
'Antigng-bot',
'Jimmy-bot',
'Jimmy-abot',
'Liangent-bot',
'Liangent-adminbot',
'Cewbot',
'WhitePhosphorus-bot'
];
Twinkle.fluff.skipTalk = null;
Twinkle.fluff.rollbackInPlace = null;
// String to insert when a username is hidden
Twinkle.fluff.hiddenName = conv({ hans: '已隐藏的用户', hant: '已隱藏的使用者' });
// Consolidated construction of fluff links
Twinkle.fluff.linkBuilder = {
spanTag: function(color, content) {
var span = document.createElement('span');
span.style.color = color;
span.appendChild(document.createTextNode(content));
return span;
},
buildLink: function(color, text) {
var link = document.createElement('a');
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', '['));
link.appendChild(Twinkle.fluff.linkBuilder.spanTag(color, text));
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', ']'));
link.href = '#';
return link;
},
/**
* @param {string} [vandal=null] - Username of the editor being reverted
* Provide a falsey value if the username is hidden, defaults to null
* @param {boolean} inline - True to create two links in a span, false
* to create three links in a div (optional)
* @param {number|string} [rev=wgCurRevisionId] - Revision ID being reverted (optional)
* @param {string} [page=wgPageName] - Page being reverted (optional)
*/
rollbackLinks: function(vandal, inline, rev, page) {
vandal = vandal || null;
var elem = inline ? 'span' : 'div';
var revNode = document.createElement(elem);
rev = parseInt(rev, 10);
if (rev) {
revNode.setAttribute('id', 'tw-revert' + rev);
} else {
revNode.setAttribute('id', 'tw-revert');
}
var normNode = document.createElement('strong');
var vandNode = document.createElement('strong');
var normLink = Twinkle.fluff.linkBuilder.buildLink('SteelBlue', '回退');
var vandLink = Twinkle.fluff.linkBuilder.buildLink('Red', conv({ hans: '破坏', hant: '破壞' }));
$(normLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('norm', vandal, rev, page);
Twinkle.fluff.disableLinks(revNode);
});
$(vandLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('vand', vandal, rev, page);
Twinkle.fluff.disableLinks(revNode);
});
vandNode.appendChild(vandLink);
normNode.appendChild(normLink);
var separator = inline ? ' ' : ' || ';
if (!inline) {
var agfNode = document.createElement('strong');
var agfLink = Twinkle.fluff.linkBuilder.buildLink('DarkOliveGreen', '回退(AGF)');
$(agfLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revert('agf', vandal, rev, page);
// Twinkle.fluff.disableLinks(revNode); // rollbackInPlace not relevant for any inline situations
});
agfNode.appendChild(agfLink);
revNode.appendChild(agfNode);
}
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(normNode);
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(vandNode);
return revNode;
},
// Build [restore this revision] links
restoreThisRevisionLink: function(revisionRef, inline) {
// If not a specific revision number, should be wgDiffNewId/wgDiffOldId/wgRevisionId
revisionRef = typeof revisionRef === 'number' ? revisionRef : mw.config.get(revisionRef);
var elem = inline ? 'span' : 'div';
var revertToRevisionNode = document.createElement(elem);
revertToRevisionNode.setAttribute('id', 'tw-revert-to-' + revisionRef);
revertToRevisionNode.style.fontWeight = 'bold';
var revertToRevisionLink = Twinkle.fluff.linkBuilder.buildLink('SaddleBrown', conv({ hans: '恢复此版本', hant: '恢復此版本' }));
$(revertToRevisionLink).click(function(e) {
e.preventDefault();
Twinkle.fluff.revertToRevision(revisionRef);
});
if (inline) {
revertToRevisionNode.appendChild(document.createTextNode(' '));
}
revertToRevisionNode.appendChild(revertToRevisionLink);
return revertToRevisionNode;
}
};
Twinkle.fluff.addLinks = {
contributions: function() {
// $('sp-contributions-footer-anon-range') relies on the fmbox
// id in [[MediaWiki:Sp-contributions-footer-anon-range]] and
// is used to show rollback/vandalism links for IP ranges
var isRange = !!$('#sp-contributions-footer-anon-range')[0];
if (mw.config.exists('wgRelevantUserName') || isRange) {
// Get the username these contributions are for
var username = mw.config.get('wgRelevantUserName');
if (Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 ||
(mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1) ||
(mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1)) {
var $list = $('#mw-content-text').find('ul li:has(span.mw-uctop):has(.mw-changeslist-diff)');
$list.each(function(key, current) {
// revid is also available in the href of both
// .mw-changeslist-date or .mw-changeslist-diff
var page = $(current).find('.mw-contributions-title').text();
// Get username for IP ranges (wgRelevantUserName is null)
if (isRange) {
// The :not is possibly unnecessary, as it appears that
// .mw-userlink is simply not present if the username is hidden
username = $(current).find('.mw-userlink:not(.history-deleted)').text();
}
// It's unlikely, but we can't easily check for revdel'd usernames
// since only a strong element is provided, with no easy selector [[phab:T255903]]
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(username, true, current.dataset.mwRevid, page));
});
}
}
},
recentchanges: function() {
if (
(mw.config.get('wgCanonicalSpecialPageName') === 'Recentchanges' && Twinkle.getPref('showRollbackLinks').indexOf('recentchanges') !== -1)
|| (mw.config.get('wgCanonicalSpecialPageName') === 'Recentchangeslinked' && Twinkle.getPref('showRollbackLinks').indexOf('recentchangeslinked') !== -1)
) {
// Latest and revertable (not page creations, logs, categorizations, etc.)
var $list = $('.mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit');
// Exclude top-level header if "group changes" preference is used
// and find only individual lines or nested lines
$list = $list.not('.mw-rcfilters-ui-highlights-enhanced-toplevel').find('.mw-changeslist-line-inner, td.mw-enhanced-rc-nested');
$list.each(function(key, current) {
// The :not is possibly unnecessary, as it appears that
// .mw-userlink is simply not present if the username is hidden
var vandal = $(current).find('.mw-userlink:not(.history-deleted)').text();
var href = $(current).find('.mw-changeslist-diff').attr('href');
var rev = mw.util.getParamValue('diff', href);
var page = current.dataset.targetPage;
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(vandal, true, rev, page));
});
}
},
history: function() {
if (Twinkle.getPref('showRollbackLinks').indexOf('history') !== -1) {
// All revs
var histList = $('#pagehistory li').toArray();
// On first page of results, so add revert/rollback
// links to the top revision
if (!$('a.mw-firstlink').length) {
var first = histList.shift();
var vandal = $(first).find('.mw-userlink:not(.history-deleted)').text();
// Check for first username different than the top user,
// only apply rollback links if/when found
// for faster than every
for (var i = 0; i < histList.length; i++) {
if ($(histList[i]).find('.mw-userlink').text() !== vandal) {
first.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(vandal, true));
break;
}
}
}
// oldid
histList.forEach(function(rev) {
// From restoreThisRevision, non-transferable
// If the text has been revdel'd, it gets wrapped in a span with .history-deleted,
// and href will be undefined (and thus oldid is NaN)
var href = rev.querySelector('.mw-changeslist-date').href;
var oldid = parseInt(mw.util.getParamValue('oldid', href), 10);
if (!isNaN(oldid)) {
rev.appendChild(Twinkle.fluff.linkBuilder.restoreThisRevisionLink(oldid, true));
}
});
}
},
diff: function() {
// Autofill user talk links on diffs with vanarticle for easy warning, but don't autowarn
var warnFromTalk = function(xtitle) {
var talkLink = $('#mw-diff-' + xtitle + '2 .mw-usertoollinks a').first();
if (talkLink.length) {
var extraParams = 'vanarticle=' + mw.util.rawurlencode(Morebits.pageNameNorm) + '&' + 'noautowarn=true';
// diffIDs for vanarticlerevid
extraParams += '&vanarticlerevid=';
extraParams += xtitle === 'otitle' ? mw.config.get('wgDiffOldId') : mw.config.get('wgDiffNewId');
var href = talkLink.attr('href');
if (href.indexOf('?') === -1) {
talkLink.attr('href', href + '?' + extraParams);
} else {
talkLink.attr('href', href + '&' + extraParams);
}
}
};
// Older revision
warnFromTalk('otitle'); // Add quick-warn link to user talk link
// Don't load if there's a single revision or weird diff (cur on latest)
if (mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId'))) {
// Add a [restore this revision] link to the older revision
var oldTitle = document.getElementById('mw-diff-otitle1').parentNode;
var revertToRevision = Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffOldId');
oldTitle.insertBefore(revertToRevision, oldTitle.firstChild);
if (Twinkle.getPref('customRevertSummary').length > 0) {
revertToRevision.appendChild(document.createTextNode(' || '));
var revertsummary = new Morebits.quickForm.element({ type: 'select', name: 'revertsummary' });
revertsummary.append({
type: 'option',
label: conv({ hans: '选择回退理由', hant: '選擇回退理由' }),
value: ''
});
$(Twinkle.getPref('customRevertSummary')).each(function(_, e) {
revertsummary.append({
type: 'option',
label: e.label,
value: e.value
});
});
revertToRevision.appendChild(revertsummary.render().childNodes[0]);
}
}
// Newer revision
warnFromTalk('ntitle'); // Add quick-warn link to user talk link
// Add either restore or rollback links to the newer revision
// Don't show if there's a single revision or weird diff (prev on first)
if (document.getElementById('differences-nextlink')) {
// Not latest revision, add [restore this revision] link to newer revision
var newTitle = document.getElementById('mw-diff-ntitle1').parentNode;
newTitle.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffNewId'), newTitle.firstChild);
} else if (Twinkle.getPref('showRollbackLinks').indexOf('diff') !== -1 && mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId') || document.getElementById('differences-prevlink'))) {
// Normally .mw-userlink is a link, but if the
// username is hidden, it will be a span with
// .history-deleted as well. When a sysop views the
// hidden content, the span contains the username in a
// link element, which will *just* have
// .mw-userlink. The below thus finds the first
// instance of the class, which if hidden is the span
// and thus text returns undefined. Technically, this
// is a place where sysops *could* have more
// information available to them (as above, via
// &unhide=1), since the username will be available by
// checking a.mw-userlink instead, but revert() will
// need reworking around userHidden
var vandal = $('#mw-diff-ntitle2').find('.mw-userlink')[0].text;
var ntitle = document.getElementById('mw-diff-ntitle1').parentNode;
ntitle.insertBefore(Twinkle.fluff.linkBuilder.rollbackLinks(vandal), ntitle.firstChild);
}
},
oldid: function() { // Add a [restore this revision] link on old revisions
var title = document.getElementById('mw-revision-info').parentNode;
title.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgRevisionId'), title.firstChild);
}
};
Twinkle.fluff.disableLinks = function disablelinks(parentNode) {
// Array.from not available in IE11 :(
$(parentNode).children().each(function(_ix, node) {
node.innerHTML = node.textContent; // Feels like cheating
$(node).css('font-weight', 'normal').css('color', 'darkgray');
});
};
Twinkle.fluff.revert = function revertPage(type, vandal, rev, page) {
if (mw.util.isIPv6Address(vandal)) {
vandal = Morebits.sanitizeIPv6(vandal);
}
var pagename = page || mw.config.get('wgPageName');
var revid = rev || mw.config.get('wgCurRevisionId');
var summary = '';
if (document.getElementsByName('revertsummary')[0] !== undefined) {
summary = document.getElementsByName('revertsummary')[0].value;
}
if (Twinkle.fluff.rollbackInPlace) {
var notifyStatus = document.createElement('span');
mw.notify(notifyStatus, {
autoHide: false,
title: '回退' + page,
tag: 'twinklefluff_' + rev // Shouldn't be necessary given disableLink
});
Morebits.status.init(notifyStatus);
} else {
Morebits.status.init(document.getElementById('mw-content-text'));
$('#catlinks').remove();
}
var params = {
type: type,
user: vandal,
userHidden: !vandal, // Keep track of whether the username was hidden
pagename: pagename,
revid: revid,
summary: summary
};
var query = {
action: 'query',
prop: ['info', 'revisions'],
titles: pagename,
intestactions: 'edit',
rvlimit: Twinkle.getPref('revertMaxRevisions'),
rvprop: [ 'ids', 'timestamp', 'user' ],
curtimestamp: '',
meta: 'tokens',
type: 'csrf'
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取较早修订版本信息', hant: '抓取較早修訂版本資訊' }), query, Twinkle.fluff.callbacks.main);
wikipedia_api.params = params;
wikipedia_api.post();
};
Twinkle.fluff.revertToRevision = function revertToRevision(oldrev) {
var summary = '';
if (document.getElementsByName('revertsummary')[0] !== undefined) {
summary = document.getElementsByName('revertsummary')[0].value;
}
Morebits.status.init(document.getElementById('mw-content-text'));
var query = {
action: 'query',
prop: ['info', 'revisions'],
titles: mw.config.get('wgPageName'),
rvlimit: 1,
rvstartid: oldrev,
rvprop: [ 'ids', 'user' ],
format: 'xml',
curtimestamp: '',
meta: 'tokens',
type: 'csrf'
};
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '抓取较早修订版本信息', hant: '抓取較早修訂版本資訊' }), query, Twinkle.fluff.callbacks.toRevision);
wikipedia_api.params = { rev: oldrev, summary: summary };
wikipedia_api.post();
};
Twinkle.fluff.callbacks = {
toRevision: function(apiobj) {
var xmlDoc = apiobj.responseXML;
var lastrevid = parseInt($(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var loadtimestamp = $(xmlDoc).find('api').attr('curtimestamp');
var csrftoken = $(xmlDoc).find('tokens').attr('csrftoken');
var revertToRevID = parseInt($(xmlDoc).find('rev').attr('revid'), 10);
var revertToUser = $(xmlDoc).find('rev').attr('user');
var revertToUserHidden = typeof $(xmlDoc).find('rev').attr('userhidden') === 'string';
if (revertToRevID !== apiobj.params.rev) {
apiobj.statelem.error(conv({ hans: '抓取到的修订版本与请求的修订版本不符,取消。', hant: '抓取到的修訂版本與請求的修訂版本不符,取消。' }));
return;
}
var optional_summary = prompt(conv({ hans: '请输入回退理由:', hant: '請輸入回退理由:' }) + ' ', apiobj.params.summary); // padded out to widen prompt in Firefox
if (optional_summary === null) {
apiobj.statelem.error(conv({ hans: '由用户取消。', hant: '由使用者取消。' }));
return;
}
var summary = Twinkle.fluff.formatSummary(conv({ hans: '回退到由$USER做出的修订版本', hant: '回退到由$USER做出的修訂版本' }) + revertToRevID,
revertToUserHidden ? null : revertToUser, optional_summary);
var query = {
action: 'edit',
title: mw.config.get('wgPageName'),
summary: summary,
tags: Twinkle.changeTags,
token: csrftoken,
undo: lastrevid,
undoafter: revertToRevID,
basetimestamp: touched,
starttimestamp: loadtimestamp,
minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf('torev') !== -1 ? true : undefined,
bot: true
};
// Handle watching, possible expiry
if (Twinkle.getPref('watchRevertedPages').indexOf('torev') !== -1) {
var watchOrExpiry = Twinkle.getPref('watchRevertedExpiry');
if (!watchOrExpiry || watchOrExpiry === 'no') {
query.watchlist = 'nochange';
} else if (watchOrExpiry === 'default' || watchOrExpiry === 'preferences') {
query.watchlist = 'preferences';
} else {
query.watchlist = 'watch';
// number allowed but not used in Twinkle.config.watchlistEnums
if (typeof watchOrExpiry === 'string' && watchOrExpiry !== 'yes') {
query.watchlistexpiry = watchOrExpiry;
}
}
}
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = '回退完成';
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '保存回退内容', hant: '儲存回退內容' }), query, Twinkle.fluff.callbacks.complete, apiobj.statelem);
wikipedia_api.params = apiobj.params;
wikipedia_api.post();
},
main: function(apiobj) {
var xmlDoc = apiobj.responseXML;
if (typeof $(xmlDoc).find('actions').attr('edit') === 'undefined') {
apiobj.statelem.error("Unable to edit the page, it's probably protected.");
return;
}
var lastrevid = parseInt($(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var loadtimestamp = $(xmlDoc).find('api').attr('curtimestamp');
var csrftoken = $(xmlDoc).find('tokens').attr('csrftoken');
var revs = $(xmlDoc).find('rev');
var statelem = apiobj.statelem;
var params = apiobj.params;
if (revs.length < 1) {
statelem.error(conv({ hans: '没有其它修订版本,无法回退', hant: '沒有其它修訂版本,無法回退' }));
return;
}
var top = revs[0];
var lastuser = top.getAttribute('user');
if (lastrevid < params.revid) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), [conv({ hans: '从服务器获取的最新修订版本ID ', hant: '從伺服器取得的最新修訂版本ID ' }), Morebits.htmlNode('strong', lastrevid), conv({ hans: ' 小于目前所显示的修订版本ID。这可能意味着当前修订版本已被删除、服务器延迟、或抓取到了坏掉的信息。取消。', hant: ' 小於目前所顯示的修訂版本ID。這可能意味著當前修訂版本已被刪除、伺服器延遲、或擷取到了壞掉的資訊。取消。' })]);
return;
}
// Used for user-facing alerts, messages, etc., not edits or summaries
var userNorm = params.user || Twinkle.fluff.hiddenName;
var index = 1;
if (params.revid !== lastrevid) {
Morebits.status.warn('警告', [conv({ hans: '最新修订版本 ', hant: '最新修訂版本 ' }), Morebits.htmlNode('strong', lastrevid), conv({ hans: ' 与我们的修订版本 ', hant: ' 與我們的修訂版本 ' }), Morebits.htmlNode('strong', params.revid), conv({ hans: '不同', hant: ' 不同' })]);
if (lastuser === params.user) {
switch (params.type) {
case 'vand':
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,因我们假定破坏,继续回退操作。', hant: ' 做出,因我們假定破壞,繼續回退操作。' })]);
break;
case 'agf':
Morebits.status.warn('警告', [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,因我们假定善意,取消回退操作,因为问题可能已被修复。', hant: ' 做出,因我們假定善意,取消回退操作,因為問題可能已被修復。' })]);
return;
default:
Morebits.status.warn('提示', [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 做出,但我们还是不回退了。', hant: ' 做出,但我們還是不回退了。' })]);
return;
}
} else if (params.type === 'vand' &&
// Okay to test on user since it will either fail or sysop will correctly access it
// Besides, none of the trusted bots are going to be revdel'd
Twinkle.fluff.trustedBots.indexOf(top.getAttribute('user')) !== -1 && revs.length > 1 &&
revs[1].getAttribute('revid') === params.revid) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', lastuser), conv({ hans: ',一个可信的机器人做出,但之前的版本被认为是破坏,继续回退操作。', hant: ',一個可信的機器人做出,但之前的版本被認為是破壞,繼續回退操作。' })]);
index = 2;
} else {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), [conv({ hans: '最新修订版本由 ', hant: '最新修訂版本由 ' }), Morebits.htmlNode('strong', lastuser), conv({ hans: ' 做出,所以这个修订版本可能已经被回退了,取消回退操作。', hant: ' 做出,所以這個修訂版本可能已經被回退了,取消回退操作。' })]);
return;
}
} else {
// Expected revision is the same, so the users must match;
// this allows sysops to know whether the users are the same
params.user = lastuser;
userNorm = params.user || Twinkle.fluff.hiddenName;
}
if (Twinkle.fluff.trustedBots.indexOf(params.user) !== -1) {
switch (params.type) {
case 'vand':
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行破坏回退,这是一个可信的机器人,我们假定您要回退前一个修订版本。', hant: ' 執行破壞回退,這是一個可信的機器人,我們假定您要回退前一個修訂版本。' })]);
index = 2;
params.user = revs[1].getAttribute('user');
params.userHidden = revs[1].getAttribute('userhidden') === '';
break;
case 'agf':
Morebits.status.warn('提示', [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行善意回退,但这是一个可信的机器人,取消回退操作。', hant: ' 執行善意回退,但這是一個可信的機器人,取消回退操作。' })]);
return;
case 'norm':
/* falls through */
default:
var cont = confirm(conv({ hans: '选择了常规回退,但最新修改是由一个可信的机器人(', hant: '選擇了常規回退,但最新修改是由一個可信的機器人(' }) + userNorm + conv({ hans: ')做出的。确定以回退前一个修订版本,取消以回退机器人的修改', hant: ')做出的。確定以回退前一個修訂版本,取消以回退機器人的修改' }));
if (cont) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行常规回退,这是一个可信的机器人,基于确认,我们将回退前一个修订版本。', hant: ' 執行常規回退,這是一個可信的機器人,基於確認,我們將回退前一個修訂版本。' })]);
index = 2;
params.user = revs[1].getAttribute('user');
params.userHidden = revs[1].getAttribute('userhidden') === '';
userNorm = params.user || Twinkle.fluff.hiddenName;
} else {
Morebits.status.warn('提示', [conv({ hans: '将对 ', hant: '將對 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 执行常规回退,这是一个可信的机器人,基于确认,我们仍将回退这个修订版本。', hant: ' 執行常規回退,這是一個可信的機器人,基於確認,我們仍將回退這個修訂版本。' })]);
}
break;
}
}
var found = false;
var count = 0;
for (var i = index; i < revs.length; ++i) {
++count;
if (revs[i].getAttribute('user') !== params.user) {
found = i;
break;
}
}
if (!found) {
statelem.error([conv({ hans: '未找到之前的修订版本,可能 ', hant: '未找到之前的修訂版本,可能 ' }), Morebits.htmlNode('strong', userNorm), conv({ hans: ' 是唯一贡献者,或这个用户连续做出了超过 ', hant: ' 是唯一貢獻者,或這個用戶連續做出了超過 ' }) + mw.language.convertNumber(Twinkle.getPref('revertMaxRevisions')) + conv({ hans: ' 次编辑。', hant: ' 次編輯。' })]);
return;
}
if (!count) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '我们将要回退0个修订版本,这没有意义,所以取消回退操作。可能是因为这个修订版本已经被回退,但修订版本ID仍是一样的。', hant: '我們將要回退0個修訂版本,這沒有意義,所以取消回退操作。可能是因為這個修訂版本已經被回退,但修訂版本ID仍是一樣的。' }));
return;
}
var good_revision = revs[found];
var userHasAlreadyConfirmedAction = false;
if (params.type !== 'vand' && count > 1) {
if (!confirm(userNorm + conv({ hans: ' 连续做出了 ', hant: ' 連續做出了 ' }) + mw.language.convertNumber(count) + conv({ hans: ' 次编辑,是否要全部回退?', hant: ' 次編輯,是否要全部回退?' }))) {
Morebits.status.info('提示', conv({ hans: '用户取消操作', hant: '使用者取消操作' }));
return;
}
userHasAlreadyConfirmedAction = true;
}
params.count = count;
params.goodid = good_revision.getAttribute('revid');
params.gooduser = good_revision.getAttribute('user');
params.gooduserHidden = good_revision.getAttribute('userhidden') === '';
statelem.status([Morebits.htmlNode('strong', mw.language.convertNumber(count)), conv({ hans: ' 个修订版本之前由 ', hant: ' 個修訂版本之前由 ' }), Morebits.htmlNode('strong', params.gooduserHidden ? Twinkle.fluff.hiddenName : params.gooduser), conv({ hans: ' 做出的修订版本 ', hant: ' 做出的修訂版本 ' }), Morebits.htmlNode('strong', params.goodid)]);
var summary, extra_summary;
switch (params.type) {
case 'agf':
extra_summary = prompt(conv({ hans: '可选的编辑摘要:', hant: '可選的編輯摘要:' }) + ' ', params.summary); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
userHasAlreadyConfirmedAction = true;
summary = Twinkle.fluff.formatSummary(conv({ hans: '回退$USER做出的出于[[WP:AGF|善意]]的编辑', hant: '回退$USER做出的出於[[WP:AGF|善意]]的編輯' }),
params.userHidden ? null : params.user, extra_summary);
break;
case 'vand':
summary = Twinkle.fluff.formatSummary('回退$USER做出的' + params.count + conv({ hans: '次编辑,到由', hant: '次編輯,到由' }) +
(params.gooduserHidden ? Twinkle.fluff.hiddenName : params.gooduser) + conv({ hans: '做出的最后修订版本 ', hant: '做出的最後修訂版本 ' }), params.userHidden ? null : params.user);
break;
case 'norm':
/* falls through */
default:
if (Twinkle.getPref('offerReasonOnNormalRevert')) {
extra_summary = prompt(conv({ hans: '可选的编辑摘要:', hant: '可選的編輯摘要:' }) + ' ', params.summary); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
userHasAlreadyConfirmedAction = true;
}
summary = Twinkle.fluff.formatSummary('回退$USER做出的' + params.count + conv({ hans: '次编辑', hant: '次編輯' }),
params.userHidden ? null : params.user, extra_summary);
break;
}
if ((Twinkle.getPref('confirmOnFluff') ||
// Mobile user agent taken from [[en:MediaWiki:Gadget-confirmationRollback-mobile.js]]
(Twinkle.getPref('confirmOnMobileFluff') && /Android|webOS|iPhone|iPad|iPod|BlackBerry|Mobile|Opera Mini/i.test(navigator.userAgent))) &&
!userHasAlreadyConfirmedAction && !confirm(conv({ hans: '回退页面:您确定吗?', hant: '回退頁面:您確定嗎?' }))) {
statelem.error(conv({ hans: '用户取消操作。', hant: '使用者取消操作。' }));
return;
}
// Decide whether to notify the user on success
if (!Twinkle.fluff.skipTalk && Twinkle.getPref('openTalkPage').indexOf(params.type) !== -1 &&
!params.userHidden && mw.config.get('wgUserName') !== params.user) {
params.notifyUser = true;
// Pass along to the warn module
params.vantimestamp = top.getAttribute('timestamp');
}
var query = {
action: 'edit',
title: params.pagename,
summary: summary,
tags: Twinkle.changeTags,
token: csrftoken,
undo: lastrevid,
undoafter: params.goodid,
basetimestamp: touched,
starttimestamp: loadtimestamp,
minor: Twinkle.getPref('markRevertedPagesAsMinor').indexOf(params.type) !== -1 ? true : undefined,
bot: true
};
// Handle watching, possible expiry
if (Twinkle.getPref('watchRevertedPages').indexOf(params.type) !== -1) {
var watchOrExpiry = Twinkle.getPref('watchRevertedExpiry');
if (!watchOrExpiry || watchOrExpiry === 'no') {
query.watchlist = 'nochange';
} else if (watchOrExpiry === 'default' || watchOrExpiry === 'preferences') {
query.watchlist = 'preferences';
} else {
query.watchlist = 'watch';
// number allowed but not used in Twinkle.config.watchlistEnums
if (typeof watchOrExpiry === 'string' && watchOrExpiry !== 'yes') {
query.watchlistexpiry = watchOrExpiry;
}
}
}
if (!Twinkle.fluff.rollbackInPlace) {
Morebits.wiki.actionCompleted.redirect = params.pagename;
}
Morebits.wiki.actionCompleted.notice = '回退完成';
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '保存回退内容', hant: '儲存回退內容' }), query, Twinkle.fluff.callbacks.complete, statelem);
wikipedia_api.params = params;
wikipedia_api.post();
},
complete: function (apiobj) {
// TODO Most of this is copy-pasted from Morebits.wiki.page#fnSaveSuccess. Unify it
var xml = apiobj.getXML();
var $edit = $(xml).find('edit');
if ($(xml).find('captcha').length > 0) {
apiobj.statelem.error(conv({ hans: '不能回退,因维基服务器要求您输入验证码。', hant: '不能回退,因維基伺服器要求您輸入驗證碼。' }));
} else if ($edit.attr('nochange') === '') {
apiobj.statelem.error(conv({ hans: '要回退到的版本与当前版本相同,没什么要做的', hant: '要回退到的版本與目前版本相同,沒什麼要做的' }));
} else {
apiobj.statelem.info('完成');
var params = apiobj.params;
if (params.notifyUser && !params.userHidden) { // notifyUser only from main, not from toRevision
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), [conv({ hans: '开启用户 ', hant: '開啟使用者 ' }), Morebits.htmlNode('strong', params.user), conv({ hans: ' 的讨论页', hant: ' 的討論頁' })]);
var windowQuery = {
title: 'User talk:' + params.user,
action: 'edit',
preview: 'yes',
vanarticle: params.pagename.replace(/_/g, ' '),
vanarticlerevid: params.revid,
vantimestamp: params.vantimestamp,
vanarticlegoodrevid: params.goodid,
type: params.type,
count: params.count
};
switch (Twinkle.getPref('userTalkPageMode')) {
case 'tab':
window.open(mw.util.getUrl('', windowQuery), '_blank');
break;
case 'blank':
window.open(mw.util.getUrl('', windowQuery), '_blank',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
case 'window':
/* falls through */
default:
window.open(mw.util.getUrl('', windowQuery),
window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
}
}
}
}
};
// If builtInString contains the string "$USER", it will be replaced
// by an appropriate user link if a user name is provided
Twinkle.fluff.formatSummary = function(builtInString, userName, customString) {
var result = builtInString;
// append user's custom reason
if (customString) {
result += ':' + Morebits.string.toUpperCaseFirstChar(customString);
}
// find number of UTF-8 bytes the resulting string takes up, and possibly add
// a contributions or contributions+talk link if it doesn't push the edit summary
// over the 499-byte limit
if (/\$USER/.test(builtInString)) {
if (userName) {
var resultLen = unescape(encodeURIComponent(result.replace('$USER', ''))).length;
var contribsLink = '[[Special:Contributions/' + userName + '|' + userName + ']]';
var contribsLen = unescape(encodeURIComponent(contribsLink)).length;
if (resultLen + contribsLen <= 499) {
var talkLink = '([[User talk:' + userName + conv({ hans: '|讨论]])', hant: '|討論]])' });
if (resultLen + contribsLen + unescape(encodeURIComponent(talkLink)).length <= 499) {
result = Morebits.string.safeReplace(result, '$USER', contribsLink + talkLink);
} else {
result = Morebits.string.safeReplace(result, '$USER', contribsLink);
}
} else {
result = Morebits.string.safeReplace(result, '$USER', userName);
}
} else {
result = Morebits.string.safeReplace(result, '$USER', Twinkle.fluff.hiddenName);
}
}
return result;
};
Twinkle.addInitCallback(Twinkle.fluff, 'fluff');
})(jQuery);
// </nowiki>
974e8421ae70d63b498f359538bce3bab0d2ed63
MediaWiki:Gadget-twinklebatchdelete.js
8
166
335
334
2024-08-03T04:07:30Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklebatchdelete.js: Batch delete module (sysops only)
****************************************
* Mode of invocation: Tab ("D-batch")
* Active on: Existing non-articles, and Special:PrefixIndex
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.batchdelete = function twinklebatchdelete() {
if (
Morebits.userIsSysop && (
(mw.config.get('wgCurRevisionId') && mw.config.get('wgNamespaceNumber') > 0) ||
mw.config.get('wgCanonicalSpecialPageName') === 'Prefixindex' ||
mw.config.get('wgCanonicalSpecialPageName') === 'BrokenRedirects'
)
) {
Twinkle.addPortletLink(Twinkle.batchdelete.callback, conv({ hans: '批删', hant: '批刪' }), 'tw-batch', conv({ hans: '删除此分类或页面中的所有链接', hant: '刪除此分類或頁面中的所有連結' }));
}
};
Twinkle.batchdelete.unlinkCache = {};
// Has the subpages list been loaded?
var subpagesLoaded;
Twinkle.batchdelete.callback = function twinklebatchdeleteCallback() {
subpagesLoaded = false;
var Window = new Morebits.simpleWindow(600, 400);
Window.setTitle(conv({ hans: '批量删除', hant: '批次刪除' }));
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#batchdelete');
var form = new Morebits.quickForm(Twinkle.batchdelete.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除页面', hant: '刪除頁面' }),
name: 'delete_page',
value: 'delete',
checked: true,
subgroup: {
type: 'checkbox',
list: [
{
label: conv({ hans: '删除关联的讨论页(用户讨论页除外)', hant: '刪除關聯的討論頁(使用者討論頁除外)' }),
name: 'delete_talk',
value: 'delete_talk',
checked: true
},
{
label: conv({ hans: '删除到已删页面的重定向页', hant: '刪除到已刪頁面的重新導向頁面' }),
name: 'delete_redirects',
value: 'delete_redirects',
checked: true
},
{
label: conv({ hans: '删除已删页面的子页面', hant: '刪除已刪頁面的子頁面' }),
name: 'delete_subpages',
value: 'delete_subpages',
checked: false,
event: Twinkle.batchdelete.callback.toggleSubpages,
subgroup: {
type: 'checkbox',
list: [
{
label: conv({ hans: '删除已删子页面的讨论页', hant: '刪除已刪子頁面的討論頁' }),
name: 'delete_subpage_talks',
value: 'delete_subpage_talks'
},
{
label: conv({ hans: '删除到已删子页面的重定向页', hant: '刪除到已刪子頁面的重新導向頁面' }),
name: 'delete_subpage_redirects',
value: 'delete_subpage_redirects'
},
{
label: conv({ hans: '取消所有已删页面的链入(仅处理条目及Portal命名空间)', hant: '取消所有已刪頁面的連入(僅處理條目及Portal命名空間)' }),
name: 'unlink_subpages',
value: 'unlink_subpages'
}
]
}
}
]
}
},
{
label: conv({ hans: '取消链入(仅处理条目及Portal命名空间)', hant: '取消連入(僅處理條目及Portal命名空間)' }),
name: 'unlink_page',
value: 'unlink',
checked: false
},
{
label: conv({ hans: '移除文件使用(所有命名空间)', hant: '移除檔案使用(所有命名空間)' }),
name: 'unlink_file',
value: 'unlink_file',
checked: true
}
]
});
form.append({
type: 'select',
name: 'common_reason',
label: '常用理由:',
style: 'width: 85%;',
list: Twinkle.batchdelete.deletereasonlist,
event: Twinkle.batchdelete.callback.change_common_reason
});
form.append({
name: 'reason',
type: 'input',
label: '理由:',
size: 75
});
var query = {
action: 'query',
prop: 'revisions|info|imageinfo',
inprop: 'protection',
rvprop: 'size|user'
};
// On categories
if (mw.config.get('wgNamespaceNumber') === 14) {
query.generator = 'categorymembers';
query.gcmtitle = mw.config.get('wgPageName');
query.gcmlimit = Twinkle.getPref('batchMax');
// On Special:PrefixIndex
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'Prefixindex') {
query.generator = 'allpages';
query.gaplimit = Twinkle.getPref('batchMax');
if (mw.util.getParamValue('prefix')) {
query.gapnamespace = mw.util.getParamValue('namespace');
query.gapprefix = mw.util.getParamValue('prefix');
} else {
var pathSplit = decodeURIComponent(location.pathname).split('/');
if (pathSplit.length < 3 || pathSplit[2] !== 'Special:前缀索引') {
return;
}
var titleSplit = pathSplit[3].split(':');
query.gapnamespace = mw.config.get('wgNamespaceIds')[titleSplit[0].toLowerCase()];
if (titleSplit.length < 2 || typeof query.gapnamespace === 'undefined') {
query.gapnamespace = 0; // article namespace
query.gapprefix = pathSplit.splice(3).join('/');
} else {
pathSplit = pathSplit.splice(4);
pathSplit.splice(0, 0, titleSplit.splice(1).join(':'));
query.gapprefix = pathSplit.join('/');
}
}
// On Special:BrokenRedirects
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'BrokenRedirects') {
query.generator = 'querypage';
query.gqppage = 'BrokenRedirects';
query.gqplimit = Twinkle.getPref('batchMax');
// On normal pages
} else {
query.generator = 'links';
query.titles = mw.config.get('wgPageName');
query.gpllimit = Twinkle.getPref('batchMax');
}
var statusdiv = document.createElement('div');
statusdiv.style.padding = '15px'; // just so it doesn't look broken
Window.setContent(statusdiv);
Morebits.status.init(statusdiv);
Window.display();
Twinkle.batchdelete.pages = {};
var statelem = new Morebits.status(conv({ hans: '抓取页面列表', hant: '抓取頁面列表' }));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '加载中…', hant: '載入中…' }), query, function (apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page').filter(':not([missing])'); // :not([imagerepository="shared"])
$pages.each(function(index, page) {
var $page = $(page);
var ns = $page.attr('ns');
var title = $page.attr('title');
var isRedir = $page.attr('redirect') === '';
var $editprot = $page.find('pr[type="edit"][level="sysop"]');
var isProtected = $editprot.length > 0;
var size = $page.find('rev').attr('size');
var metadata = [];
if (isRedir) {
metadata.push(conv({ hans: '重定向', hant: '重新導向' }));
}
if (isProtected) {
metadata.push(conv({ hans: '全保护,', hant: '全保護,' }) +
($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)') + conv({ hans: '过期', hant: '過期' }));
}
if (ns === '6') { // mimic what delimages used to show for files
metadata.push(conv({ hans: '上传者:', hant: '上傳者:' }) + $page.find('ii').attr('user'));
metadata.push(conv({ hans: '最后编辑:', hant: '最後編輯:' }) + $page.find('rev').attr('user'));
} else {
metadata.push(mw.language.convertNumber(size) + conv({ hans: '字节', hant: '位元組' }));
}
Twinkle.batchdelete.pages[title] = {
label: title + (metadata.length ? '(' + metadata.join(',') + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
};
});
var form = apiobj.params.form;
form.append({ type: 'header', label: conv({ hans: '待删除页面', hant: '待刪除頁面' }) });
form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function dBatchSelectAll() {
$(result).find('input[name=pages]:not(:checked)').each(function(_, e) {
e.click(); // check it, and invoke click event so that subgroup can be shown
});
// Check any unchecked subpages too
$('input[name="pages.subpages"]').prop('checked', true);
}
});
form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function dBatchDeselectAll() {
$(result).find('input[name=pages]:checked').each(function(_, e) {
e.click(); // uncheck it, and invoke click event so that subgroup can be hidden
});
}
});
form.append({
type: 'checkbox',
name: 'pages',
id: 'tw-dbatch-pages',
shiftClickSupport: true,
list: $.map(Twinkle.batchdelete.pages, function (e) {
return e;
})
});
form.append({ type: 'submit' });
var result = form.render();
apiobj.params.Window.setContent(result);
Morebits.quickForm.getElements(result, 'pages').forEach(generateArrowLinks);
}, statelem);
wikipedia_api.params = { form: form, Window: Window };
wikipedia_api.post();
};
function generateArrowLinks (checkbox) {
var link = Morebits.htmlNode('a', ' >');
link.setAttribute('class', 'tw-dbatch-page-link');
link.setAttribute('href', mw.util.getUrl(checkbox.value));
link.setAttribute('target', '_blank');
checkbox.nextElementSibling.append(link);
}
Twinkle.batchdelete.generateNewPageList = function(form) {
// Update the list of checked pages in Twinkle.batchdelete.pages object
var elements = form.elements.pages;
if (elements instanceof NodeList) { // if there are multiple pages
for (var i = 0; i < elements.length; ++i) {
Twinkle.batchdelete.pages[elements[i].value].checked = elements[i].checked;
}
} else if (elements instanceof HTMLInputElement) { // if there is just one page
Twinkle.batchdelete.pages[elements.value].checked = elements.checked;
}
return new Morebits.quickForm.element({
type: 'checkbox',
name: 'pages',
id: 'tw-dbatch-pages',
shiftClickSupport: true,
list: $.map(Twinkle.batchdelete.pages, function (e) {
return e;
})
}).render();
};
Twinkle.batchdelete.deletereasonlist = [
{
label: conv({ hans: '请选择', hant: '請選擇' }),
value: ''
},
{
label: conv({ hans: 'G10: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: 'G10: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' }),
value: conv({ hans: '[[Wikipedia:CSD#G10|G10]]: 原作者清空页面或提出删除,且实际贡献者只有一人', hant: '[[Wikipedia:CSD#G10|G10]]: 原作者清空頁面或提出刪除,且實際貢獻者只有一人' })
},
{
label: conv({ hans: 'G15: 孤立页面,比如没有主页面的讨论页、指向空页面的重定向等', hant: 'G15: 孤立頁面,比如沒有主頁面的討論頁、指向空頁面的重新導向等' }),
value: conv({ hans: '[[Wikipedia:CSD#G15|G15]]: 孤立页面', hant: '[[Wikipedia:CSD#G15|G15]]: 孤立頁面' })
},
{
label: conv({ hans: 'F6: 没有被条目使用的非自由著作权文件', hant: 'F6: 沒有被條目使用的非自由著作權檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F6|F6]]: 没有被条目使用的[[Wikipedia:合理使用|非自由著作权]]文件', hant: '[[Wikipedia:CSD#F6|F6]]: 沒有被條目使用的[[Wikipedia:合理使用|非自由著作權]]檔案' })
},
{
label: conv({ hans: 'F7: 与维基共享资源文件重复的文件', hant: 'F7: 與維基共享資源檔案重複的檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F7|F7]]: 与[[维基共享资源]]文件重复的文件', hant: '[[Wikipedia:CSD#F7|F7]]: 與[[維基共享資源]]檔案重複的檔案' })
},
{
label: conv({ hans: 'F10: 可被替代的非自由著作权文件', hant: 'F10: 可被替代的非自由版權檔案' }),
value: conv({ hans: '[[Wikipedia:CSD#F10|F10]]: 可被替代的非自由著作权文件', hant: '[[Wikipedia:CSD#F10|F10]]: 可被替代的非自由版權檔案' })
},
{
label: conv({ hans: 'O1: 用户请求删除自己的用户页或其子页面', hant: 'O1: 使用者請求刪除自己的使用者頁面或其子頁面' }),
value: conv({ hans: '[[Wikipedia:CSD#O1|O1]]: 用户请求删除自己的[[Help:用户页|用户页]]或其子页面。', hant: '[[Wikipedia:CSD#O1|O1]]: 使用者請求刪除自己的[[Help:用户页|使用者頁面]]或其子頁面。' })
},
{
label: conv({ hans: 'O4: 空的分类(没有条目也没有子分类)', hant: 'O4: 空的分類(沒有條目也沒有子分類)' }),
value: conv({ hans: '[[Wikipedia:CSD#O4|O4]]: 空的分类(没有条目也没有子分类)。', hant: '[[Wikipedia:CSD#O4|O4]]: 空的分類(沒有條目也沒有子分類)。' })
},
{
label: conv({ hans: 'O7: 废弃草稿', hant: 'O7: 廢棄草稿' }),
value: conv({ hans: '[[Wikipedia:CSD#O7|O7]]: 废弃草稿。', hant: '[[Wikipedia:CSD#O7|O7]]: 廢棄草稿。' })
},
{
label: conv({ hans: 'R2: 跨命名空间的重定向', hant: 'R2: 跨命名空間的重新導向' }),
value: conv({ hans: '[[WP:CSD#R2|R2]]: 跨[[H:NS|命名空间]]的[[WP:R|重定向]]', hant: '[[WP:CSD#R2|R2]]: 跨[[H:NS|命名空間]]的[[WP:R|重新導向]]' })
}
];
Twinkle.batchdelete.callback.change_common_reason = function twinklebatchdeleteCallbackChangeCustomReason(e) {
if (e.target.form.reason.value !== '') {
e.target.form.reason.value = Morebits.string.appendPunctuation(e.target.form.reason.value);
}
e.target.form.reason.value += e.target.value;
e.target.value = '';
};
Twinkle.batchdelete.callback.toggleSubpages = function twDbatchToggleSubpages(e) {
var form = e.target.form;
var newPageList;
if (e.target.checked) {
form.delete_subpage_redirects.checked = form.delete_redirects.checked;
form.delete_subpage_talks.checked = form.delete_talk.checked;
form.unlink_subpages.checked = form.unlink_page.checked;
// If lists of subpages were already loaded once, they are
// available without use of any API calls
if (subpagesLoaded) {
$.each(Twinkle.batchdelete.pages, function(i, el) {
// Get back the subgroup from subgroup_, where we saved it
if (el.subgroup === null && el.subgroup_) {
el.subgroup = el.subgroup_;
}
});
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
Morebits.quickForm.getElements(newPageList, 'pages.subpages').forEach(generateArrowLinks);
return;
}
// Proceed with API calls to get list of subpages
var loadingText = '<strong id="dbatch-subpage-loading">' + conv({ hans: '加载中...', hant: '載入中...' }) + '</strong>';
$(e.target).after(loadingText);
var pages = $(form.pages).map(function(i, el) {
return el.value;
}).get();
var subpageLister = new Morebits.batchOperation();
subpageLister.setOption('chunkSize', Twinkle.getPref('batchChunks'));
subpageLister.setPageList(pages);
subpageLister.run(function worker (pageName) {
var pageTitle = mw.Title.newFromText(pageName);
// No need to look for subpages in main/file/mediawiki space
if ([0, 6, 8].indexOf(pageTitle.namespace) > -1) {
subpageLister.workerSuccess();
return;
}
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取 ', hant: '正在取得 ' }) + pageName + conv({ hans: ' 的子页面', hant: ' 的子頁面' }), {
action: 'query',
prop: 'revisions|info|imageinfo',
generator: 'allpages',
rvprop: 'size',
inprop: 'protection',
gapprefix: pageTitle.title + '/',
gapnamespace: pageTitle.namespace,
gaplimit: 'max', // 500 is max for normal users, 5000 for bots and sysops
pageNameFull: pageName // Not used by API, but added for access in onSuccess()
}, function onSuccess(apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page');
var subpageList = [];
$pages.each(function(index, page) {
var $page = $(page);
var ns = $page.attr('ns');
var title = $page.attr('title');
var isRedir = $page.attr('redirect') === '';
var $editprot = $page.find('pr[type="edit"][level="sysop"]');
var isProtected = $editprot.length > 0;
var size = $page.find('rev').attr('size');
var metadata = [];
if (isRedir) {
metadata.push('redirect');
}
if (isProtected) {
metadata.push(conv({ hans: '全保护,', hant: '全保護,' }) +
($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)') + conv({ hans: '过期', hant: '過期' }));
}
if (ns === '6') { // mimic what delimages used to show for files
metadata.push(conv({ hans: '上传者:', hant: '上傳者:' }) + $page.find('ii').attr('user'));
metadata.push(conv({ hans: '最后编辑:', hant: '最後編輯:' }) + $page.find('rev').attr('user'));
} else {
metadata.push(mw.language.convertNumber(size) + conv({ hans: '字节', hant: '位元組' }));
}
subpageList.push({
label: title + (metadata.length ? ' (' + metadata.join('; ') + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
});
});
if (subpageList.length) {
var pageName = apiobj.query.pageNameFull;
Twinkle.batchdelete.pages[pageName].subgroup = {
type: 'checkbox',
name: 'subpages',
className: 'dbatch-subpages',
shiftClickSupport: true,
list: subpageList
};
}
subpageLister.workerSuccess();
}, null /* statusElement */, function onFailure() {
subpageLister.workerFailure();
});
wikipedia_api.post();
}, function postFinish () {
// List 'em on the interface
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
Morebits.quickForm.getElements(newPageList, 'pages.subpages').forEach(generateArrowLinks);
subpagesLoaded = true;
// Remove "Loading... " text
$('#dbatch-subpage-loading').remove();
});
} else if (!e.target.checked) {
$.each(Twinkle.batchdelete.pages, function(i, el) {
if (el.subgroup) {
// Remove subgroup after saving its contents in subgroup_
// so that it can be retrieved easily if user decides to
// delete the subpages again
el.subgroup_ = el.subgroup;
el.subgroup = null;
}
});
newPageList = Twinkle.batchdelete.generateNewPageList(form);
$('#tw-dbatch-pages').replaceWith(newPageList);
Morebits.quickForm.getElements(newPageList, 'pages').forEach(generateArrowLinks);
}
};
Twinkle.batchdelete.callback.evaluate = function twinklebatchdeleteCallbackEvaluate(event) {
Morebits.wiki.actionCompleted.notice = conv({ hans: '批量删除已完成', hant: '批次刪除已完成' });
var form = event.target;
var numProtected = $(Morebits.quickForm.getElements(form, 'pages')).filter(function(index, element) {
return element.checked && element.nextElementSibling.style.color === 'red';
}).length;
if (numProtected > 0 && !confirm(conv({ hans: '您正要删除 ', hant: '您正要刪除 ' }) + mw.language.convertNumber(numProtected) + conv({ hans: ' 个全保护页面,您确定吗?', hant: ' 個全保護頁面,您確定嗎?' }))) {
return;
}
var pages = form.getChecked('pages');
var subpages = form.getChecked('pages.subpages');
var reason = form.reason.value;
var delete_page = form.delete_page.checked;
var delete_talk, delete_redirects, delete_subpages;
var delete_subpage_redirects, delete_subpage_talks, unlink_subpages;
if (delete_page) {
delete_talk = form.delete_talk.checked;
delete_redirects = form.delete_redirects.checked;
delete_subpages = form.delete_subpages.checked;
if (delete_subpages) {
delete_subpage_redirects = form.delete_subpage_redirects.checked;
delete_subpage_talks = form.delete_subpage_talks.checked;
unlink_subpages = form.unlink_subpages.checked;
}
}
var unlink_page = form.unlink_page.checked;
var unlink_file = form.unlink_file.checked;
if (!reason) {
alert(conv({ hans: '您需要给出一个理由', hant: '您需要給出一個理由' }));
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
if (!pages) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '没有要删除的内容,中止', hant: '沒有要刪除的內容,中止' }));
return;
}
var pageDeleter = new Morebits.batchOperation(delete_page ? conv({ hans: '正在删除页面', hant: '正在刪除頁面' }) : conv({ hans: '正在启动要求的任务', hant: '正在啟動要求的任務' }));
pageDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
// we only need the initial status lines if we're deleting the pages in the pages array
pageDeleter.setOption('preserveIndividualStatusLines', delete_page);
pageDeleter.setPageList(pages);
pageDeleter.run(function worker(pageName) {
var params = {
page: pageName,
delete_page: delete_page,
delete_talk: delete_talk,
delete_redirects: delete_redirects,
unlink_page: unlink_page,
unlink_file: unlink_file && new RegExp('^' + Morebits.namespaceRegex(6) + ':', 'i').test(pageName),
reason: reason,
pageDeleter: pageDeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + pageName);
wikipedia_page.setCallbackParameters(params);
if (delete_page) {
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.deletePage(Twinkle.batchdelete.callbacks.doExtras, pageDeleter.workerFailure);
} else {
Twinkle.batchdelete.callbacks.doExtras(wikipedia_page);
}
}, function postFinish() {
if (delete_subpages) {
var subpageDeleter = new Morebits.batchOperation(conv({ hans: '正在删除子页面', hant: '正在刪除子頁面' }));
subpageDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
subpageDeleter.setOption('preserveIndividualStatusLines', true);
subpageDeleter.setPageList(subpages);
subpageDeleter.run(function(pageName) {
var params = {
page: pageName,
delete_page: true,
delete_talk: delete_subpage_talks,
delete_redirects: delete_subpage_redirects,
unlink_page: unlink_subpages,
unlink_file: false,
reason: reason,
pageDeleter: subpageDeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除子页面 ', hant: '正在刪除子頁面 ' }) + pageName);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.deletePage(Twinkle.batchdelete.callbacks.doExtras, pageDeleter.workerFailure);
});
}
});
};
Twinkle.batchdelete.callbacks = {
// this stupid parameter name is a temporary thing until I implement an overhaul
// of Morebits.wiki.* callback parameters
doExtras: function(thingWithParameters) {
var params = thingWithParameters.parent ? thingWithParameters.parent.getCallbackParameters() :
thingWithParameters.getCallbackParameters();
// the initial batch operation's job is to delete the page, and that has
// succeeded by now
params.pageDeleter.workerSuccess(thingWithParameters);
var query, wikipedia_api;
if (params.unlink_page) {
Twinkle.batchdelete.unlinkCache = {};
query = {
action: 'query',
list: 'backlinks',
blfilterredir: 'nonredirects',
blnamespace: [0, 100], // main space and portal space only
bltitle: params.page,
bllimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取链入', hant: '正在取得連入' }), query, Twinkle.batchdelete.callbacks.unlinkBacklinksMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.unlink_file) {
query = {
action: 'query',
list: 'imageusage',
iutitle: params.page,
iulimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取文件链入', hant: '正在取得檔案連入' }), query, Twinkle.batchdelete.callbacks.unlinkImageInstancesMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.delete_page) {
if (params.delete_redirects) {
query = {
action: 'query',
titles: params.page,
prop: 'redirects',
rdlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取重定向', hant: '正在取得重新導向' }), query, Twinkle.batchdelete.callbacks.deleteRedirectsMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.delete_talk) {
var pageTitle = mw.Title.newFromText(params.page);
if (pageTitle && pageTitle.namespace % 2 === 0 && pageTitle.namespace !== 2) {
pageTitle.namespace++; // now pageTitle is the talk page title!
query = {
action: 'query',
titles: pageTitle.toText()
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在检查讨论页面是否存在', hant: '正在檢查討論頁面是否存在' }), query, Twinkle.batchdelete.callbacks.deleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = pageTitle.toText();
wikipedia_api.post();
}
}
}
},
deleteRedirectsMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('rd').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var redirectDeleter = new Morebits.batchOperation(conv({ hans: '正在删除到 ', hant: '正在刪除到 ' }) + apiobj.params.page + conv({ hans: ' 的重定向', hant: ' 的重新導向' }));
redirectDeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
redirectDeleter.setPageList(pages);
redirectDeleter.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除 ', hant: '正在刪除 ' }) + pageName);
wikipedia_page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '指向已删页面“', hant: '指向已刪頁面「' }) + apiobj.params.page + conv({ hans: '”的重定向', hant: '」的重新導向' }));
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.deletePage(redirectDeleter.workerSuccess, redirectDeleter.workerFailure);
});
},
deleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
if (!exists) {
// no talk page; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + apiobj.params.page + conv({ hans: ' 的讨论页', hant: ' 的討論頁' }));
page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '已删页面“', hant: '已刪頁面「' }) + apiobj.params.page + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.deletePage();
},
unlinkBacklinksMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('bl').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var unlinker = new Morebits.batchOperation('正在取消到 ' + apiobj.params.page + conv({ hans: ' 的链入', hant: ' 的連入' }));
unlinker.setOption('chunkSize', Twinkle.getPref('batchChunks'));
unlinker.setPageList(pages);
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, '正在取消 ' + pageName + conv({ hans: ' 上的链入', hant: ' 上的連入' }));
var params = $.extend({}, apiobj.params);
params.title = pageName;
params.unlinker = unlinker;
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.batchdelete.callbacks.unlinkBacklinks);
});
},
unlinkBacklinks: function(pageobj) {
var params = pageobj.getCallbackParameters();
if (!pageobj.exists()) {
// we probably just deleted it, as a recursive backlink
params.unlinker.workerSuccess(pageobj);
return;
}
var text;
if (params.title in Twinkle.batchdelete.unlinkCache) {
text = Twinkle.batchdelete.unlinkCache[params.title];
} else {
text = pageobj.getPageText();
}
var old_text = text;
var wikiPage = new Morebits.wikitext.page(text);
text = wikiPage.removeLink(params.page).getText();
Twinkle.batchdelete.unlinkCache[params.title] = text;
if (text === old_text) {
// Nothing to do, return
params.unlinker.workerSuccess(pageobj);
return;
}
pageobj.setEditSummary(conv({ hans: '取消到已删页面', hant: '取消到已刪頁面' }) + params.page + conv({ hans: '的链入', hant: '的連入' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setPageText(text);
pageobj.setCreateOption('nocreate');
pageobj.setMaxConflictRetries(10);
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
},
unlinkImageInstancesMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('iu').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var unlinker = new Morebits.batchOperation('正在取消到 ' + apiobj.params.page + conv({ hans: ' 的链入', hant: ' 的連入' }));
unlinker.setOption('chunkSize', Twinkle.getPref('batchChunks'));
unlinker.setPageList(pages);
unlinker.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, '取消 ' + pageName + conv({ hans: ' 的文件使用', hant: ' 的檔案使用' }));
var params = $.extend({}, apiobj.params);
params.title = pageName;
params.unlinker = unlinker;
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.batchdelete.callbacks.unlinkImageInstances);
});
},
unlinkImageInstances: function(pageobj) {
var params = pageobj.getCallbackParameters();
if (!pageobj.exists()) {
// we probably just deleted it, as a recursive backlink
params.unlinker.workerSuccess(pageobj);
return;
}
var image = params.page.replace(new RegExp('^' + Morebits.namespaceRegex(6) + ':'), '');
var text;
if (params.title in Twinkle.batchdelete.unlinkCache) {
text = Twinkle.batchdelete.unlinkCache[params.title];
} else {
text = pageobj.getPageText();
}
var old_text = text;
var wikiPage = new Morebits.wikitext.page(text);
text = wikiPage.commentOutImage(image, conv({ hans: '因文件已删,故注解', hant: '因檔案已刪,故註解' })).getText();
Twinkle.batchdelete.unlinkCache[params.title] = text;
if (text === old_text) {
pageobj.getStatusElement().error('在 ' + pageobj.getPageName() + ' 上取消 ' + image + conv({ hans: ' 的文件使用失败', hant: ' 的檔案使用失敗' }));
params.unlinker.workerFailure(pageobj);
return;
}
pageobj.setEditSummary(conv({ hans: '取消使用已被删除文件', hant: '取消使用已被刪除檔案' }) + image + conv({ hans: ',因为:', hant: ',因為:' }) + params.reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setPageText(text);
pageobj.setCreateOption('nocreate');
pageobj.setMaxConflictRetries(10);
pageobj.save(params.unlinker.workerSuccess, params.unlinker.workerFailure);
}
};
Twinkle.addInitCallback(Twinkle.batchdelete, 'batchdelete');
})(jQuery);
// </nowiki>
78e36fdf5872d8b813d05aea841267b47a7b19f7
MediaWiki:Gadget-twinklebatchundelete.js
8
167
337
336
2024-08-03T04:07:30Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinklebatchundelete.js: Batch undelete module
****************************************
* Mode of invocation: Tab ("Und-batch")
* Active on: Existing user and project pages
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.batchundelete = function twinklebatchundelete() {
if (!Morebits.userIsSysop || !mw.config.get('wgArticleId') || (
mw.config.get('wgNamespaceNumber') !== mw.config.get('wgNamespaceIds').user &&
mw.config.get('wgNamespaceNumber') !== mw.config.get('wgNamespaceIds').project)) {
return;
}
Twinkle.addPortletLink(Twinkle.batchundelete.callback, conv({ hans: '批复', hant: '批復' }), 'tw-batch-undel', conv({ hans: '反删除页面', hant: '反刪除頁面' }));
};
Twinkle.batchundelete.callback = function twinklebatchundeleteCallback() {
var Window = new Morebits.simpleWindow(600, 400);
Window.setScriptName('Twinkle');
Window.setTitle(conv({ hans: '批量反删除', hant: '批次反刪除' }));
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#batchundelete');
var form = new Morebits.quickForm(Twinkle.batchundelete.callback.evaluate);
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '如果存在已删除的讨论页,也恢复', hant: '如果存在已刪除的討論頁,也恢復' }),
name: 'undel_talk',
value: 'undel_talk',
checked: true
}
]
});
form.append({
type: 'input',
name: 'reason',
label: '理由:',
size: 60
});
var statusdiv = document.createElement('div');
statusdiv.style.padding = '15px'; // just so it doesn't look broken
Window.setContent(statusdiv);
Morebits.status.init(statusdiv);
Window.display();
var query = {
action: 'query',
generator: 'links',
prop: 'info',
inprop: 'protection',
titles: mw.config.get('wgPageName'),
gpllimit: Twinkle.getPref('batchMax')
};
var statelem = new Morebits.status(conv({ hans: '抓取页面列表', hant: '抓取頁面列表' }));
var wikipedia_api = new Morebits.wiki.api(conv({ hans: '加载中…', hant: '載入中…' }), query, function (apiobj) {
var xml = apiobj.responseXML;
var $pages = $(xml).find('page[missing]');
var list = [];
$pages.each(function(index, page) {
var $page = $(page);
var title = $page.attr('title');
var $editprot = $page.find('pr[type="create"][level="sysop"]');
var isProtected = $editprot.length > 0;
list.push({
label: title + (isProtected ? '(' + conv({ hans: '全保护,', hant: '全保護,' }) + ($editprot.attr('expiry') === 'infinity' ? conv({ hans: '无限期', hant: '無限期' }) : new Morebits.date($editprot.attr('expiry')).calendar('utc') + ' (UTC)' + conv({ hans: '过期', hant: '過期' })) + ')' : ''),
value: title,
checked: true,
style: isProtected ? 'color:red' : ''
});
});
apiobj.params.form.append({ type: 'header', label: conv({ hans: '待恢复页面', hant: '待恢復頁面' }) });
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全选', hant: '全選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', true);
}
});
apiobj.params.form.append({
type: 'button',
label: conv({ hans: '全不选', hant: '全不選' }),
event: function(e) {
$(Morebits.quickForm.getElements(e.target.form, 'pages')).prop('checked', false);
}
});
apiobj.params.form.append({
type: 'checkbox',
name: 'pages',
shiftClickSupport: true,
list: list
});
apiobj.params.form.append({ type: 'submit' });
var result = apiobj.params.form.render();
apiobj.params.Window.setContent(result);
}, statelem);
wikipedia_api.params = { form: form, Window: Window };
wikipedia_api.post();
};
Twinkle.batchundelete.callback.evaluate = function(event) {
Morebits.wiki.actionCompleted.notice = conv({ hans: '反删除已完成', hant: '反刪除已完成' });
var numProtected = $(Morebits.quickForm.getElements(event.target, 'pages')).filter(function(index, element) {
return element.checked && element.nextElementSibling.style.color === 'red';
}).length;
if (numProtected > 0 && !confirm(conv({ hans: '您正要反删除 ', hant: '您正要反刪除 ' }) + numProtected + conv({ hans: ' 个全保护页面,您确定吗?', hant: ' 個全保護頁面,您確定嗎?' }))) {
return;
}
var pages = event.target.getChecked('pages');
var reason = event.target.reason.value;
var undel_talk = event.target.reason.value;
if (!reason) {
alert('您需要指定理由。');
return;
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(event.target);
if (!pages) {
Morebits.status.error(conv({ hans: '错误', hant: '錯誤' }), conv({ hans: '没什么要反删除的,取消操作', hant: '沒什麼要反刪除的,取消操作' }));
return;
}
var pageUndeleter = new Morebits.batchOperation(conv({ hans: '反删除页面', hant: '反刪除頁面' }));
pageUndeleter.setOption('chunkSize', Twinkle.getPref('batchChunks'));
pageUndeleter.setOption('preserveIndividualStatusLines', true);
pageUndeleter.setPageList(pages);
pageUndeleter.run(function(pageName) {
var params = {
page: pageName,
undel_talk: undel_talk,
reason: reason,
pageUndeleter: pageUndeleter
};
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '反删除页面', hant: '反刪除頁面' }) + pageName);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setEditSummary(reason + ' (批量)');
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.suppressProtectWarning();
wikipedia_page.setMaxRetries(3); // temporary increase from 2 to make batchundelete more likely to succeed [[phab:T222402]] #613
wikipedia_page.undeletePage(Twinkle.batchundelete.callbacks.doExtras, pageUndeleter.workerFailure);
});
};
Twinkle.batchundelete.callbacks = {
// this stupid parameter name is a temporary thing until I implement an overhaul
// of Morebits.wiki.* callback parameters
doExtras: function(thingWithParameters) {
var params = thingWithParameters.parent ? thingWithParameters.parent.getCallbackParameters() :
thingWithParameters.getCallbackParameters();
// the initial batch operation's job is to delete the page, and that has
// succeeded by now
params.pageUndeleter.workerSuccess(thingWithParameters);
var query, wikipedia_api;
if (params.undel_talk) {
var talkpagename = new mw.Title(params.page).getTalkPage().getPrefixedText();
if (talkpagename !== params.page) {
query = {
action: 'query',
prop: 'deletedrevisions',
drvprop: 'ids',
drvlimit: 1,
titles: talkpagename
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '检查讨论页的已删版本', hant: '檢查討論頁的已刪版本' }), query, Twinkle.batchundelete.callbacks.undeleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = talkpagename;
wikipedia_api.post();
}
}
},
undeleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
var delrevs = $(xml).find('rev').attr('revid');
if (exists || !delrevs) {
// page exists or has no deleted revisions; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在反删除', hant: '正在反刪除' }) + apiobj.params.page + conv({ hans: '的讨论页', hant: '的討論頁' }));
page.setEditSummary(conv({ hans: '反删除“', hant: '反刪除「' }) + apiobj.params.page + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.undeletePage();
}
};
Twinkle.addInitCallback(Twinkle.batchundelete, 'batchundelete');
})(jQuery);
// </nowiki>
a710c6992c48f371b4b4fa581e9692cc2a7ee0d2
MediaWiki:Gadget-twinkleclose.js
8
168
339
338
2024-08-03T04:07:31Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleclose.js: XFD closing module
****************************************
* Mode of invocation: Links after section heading
* Active on: AfD dated archive pages
* Config directives in: TwinkleConfig
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.close = function twinkleclose() {
if (Twinkle.getPref('XfdClose') === 'hide' || !/^Wikipedia:(頁面|檔案)存廢討論\/記錄\/\d+\/\d+\/\d+$/.test(mw.config.get('wgPageName'))) {
return;
}
mw.hook('wikipage.content').add(function(item) {
if (item.attr('id') === 'mw-content-text') {
Twinkle.close.addLinks();
}
});
};
Twinkle.close.addLinks = function twinklecloseAddLinks() {
var prevH2Section = -1;
$('.mw-heading.mw-heading1, .mw-heading.mw-heading2, .mw-heading.mw-heading3, .mw-heading.mw-heading4, .mw-heading.mw-heading5, .mw-heading.mw-heading6', '#bodyContent').each(function (index, current) {
current.setAttribute('data-section', index + 1);
if ($(current).hasClass('mw-heading2')) {
prevH2Section = index + 1;
} else {
current.setAttribute('data-parent-section', prevH2Section);
}
});
var selector = ':has(a:only-of-type):not(:has(+ div.NavFrame))';
var titles = $('#bodyContent').find('.mw-heading2' + selector + ':not(:has(+ p + div.mw-heading.mw-heading3)), .mw-heading3' + selector);
titles.each(function(key, current) {
var $pageLink = $(current).find('h2 a, h3 a');
var headlinehref = $pageLink.attr('href');
if (headlinehref === undefined) {
return;
}
var title = null;
if (headlinehref.indexOf('redlink=1') !== -1) {
title = headlinehref.slice(19, -22);
} else {
var m = headlinehref.match(/\/wiki\/([^?]+)/, '$1');
if (m !== null) {
title = m[1];
}
}
if (title === null) {
return;
}
title = decodeURIComponent(title);
title = title.replace(/_/g, ' '); // Normalize for using in interface and summary
var pagenotexist = $pageLink.hasClass('new');
var section = current.getAttribute('data-section');
var parentSection = current.getAttribute('data-parent-section') || -1;
var node = current.getElementsByClassName('mw-editsection')[0];
var delDivider = document.createElement('span');
delDivider.appendChild(document.createTextNode(' | '));
node.insertBefore(delDivider, node.childNodes[1]);
var delLink = document.createElement('a');
delLink.className = 'twinkle-close-button';
delLink.href = '#';
delLink.setAttribute('data-section', section);
delLink.innerText = conv({ hans: '关闭讨论', hant: '關閉討論' });
$(delLink).on('click', function() {
Twinkle.close.callback(title, section, parentSection, pagenotexist);
return false;
});
node.insertBefore(delLink, node.childNodes[1]);
});
};
var date = new Morebits.date();
// Keep this synchronized with {{delh}}
Twinkle.close.codes = [{
key: conv({ hans: '请求无效', hant: '請求無效' }),
value: {
ir: {
label: conv({ hans: '请求无效', hant: '請求無效' }),
action: 'keep'
},
rep: {
label: conv({ hans: '重复提出,无效', hant: '重複提出,無效' }),
action: 'keep'
},
commons: {
label: conv({ hans: '应在维基共享资源提请', hant: '應在維基共享資源提請' }),
action: 'keep'
},
ne: {
label: conv({ hans: '目标页面或文件不存在,无效', hant: '目標頁面或檔案不存在,無效' }),
action: 'keep'
},
nq: {
label: conv({ hans: '提删者未获取提删资格,无效', hant: '提刪者未取得提刪資格,無效' }),
action: 'keep'
}
}
},
{
key: '保留',
value: {
k: {
label: '保留',
action: 'keep',
adminonly: true
},
sk: {
label: '快速保留',
action: 'keep'
},
tk: {
label: conv({ hans: '暂时保留,改挂维护模板(关注度等)', hant: '暫時保留,改掛維護模板(關注度等)' }),
value: conv({ hans: '暂时保留', hant: '暫時保留' }),
action: 'keep'
},
rr: {
label: conv({ hans: '请求理由消失', hant: '請求理由消失' }),
action: 'keep',
selected: Twinkle.getPref('XfdClose') === 'nonadminonly'
},
dan: {
label: conv({ hans: '删后重建', hant: '刪後重建' }),
action: 'keep',
adminonly: true
}
}
},
{
key: conv({ hans: '删除', hant: '刪除' }),
value: {
d: {
label: conv({ hans: '删除', hant: '刪除' }),
action: 'del',
adminonly: true,
selected: Twinkle.getPref('XfdClose') === 'all'
},
ic: {
label: conv({ hans: '图像因侵权被删', hant: '圖像因侵權被刪' }),
action: 'del',
adminonly: true
}
}
},
{
key: conv({ hans: '快速删除', hant: '快速刪除' }),
value: {
sd: {
label: conv({ hans: '快速删除', hant: '快速刪除' }),
action: 'del'
},
lssd: {
label: conv({ hans: '无来源或著作权信息,快速删除', hant: '無來源或版權資訊,快速刪除' }),
action: 'del'
},
svg: {
label: conv({ hans: '已改用SVG图形,快速删除', hant: '已改用SVG圖形,快速刪除' }),
action: 'del'
},
nowcommons: {
label: conv({ hans: '维基共享资源已提供,快速删除', hant: '維基共享資源已提供,快速刪除' }),
action: 'del'
},
drep: {
label: conv({ hans: '多次被删除,条目锁定', hant: '多次被刪除,條目鎖定' }),
action: 'del',
adminonly: true
}
}
},
{
key: conv({ hans: '转移至其他维基计划', hant: '轉移至其他維基計劃' }),
value: {
twc: {
label: conv({ hans: '转移至维基共享资源', hant: '轉移至維基共享資源' }),
action: 'noop',
adminonly: true
},
twn: {
label: conv({ hans: '转移至维基新闻', hant: '轉移至維基新聞' }),
action: 'noop',
adminonly: true
},
tws: {
label: conv({ hans: '转移至维基文库', hant: '轉移至維基文庫' }),
action: 'noop',
adminonly: true
},
twb: {
label: conv({ hans: '转移至维基教科书', hant: '轉移至維基教科書' }),
action: 'noop',
adminonly: true
},
twq: {
label: conv({ hans: '转移至维基语录', hant: '轉移至維基語錄' }),
action: 'noop',
adminonly: true
},
twt: {
label: conv({ hans: '转移至维基词典', hant: '轉移至維基詞典' }),
action: 'noop',
adminonly: true
},
twv: {
label: conv({ hans: '转移至维基学院', hant: '轉移至維基學院' }),
action: 'noop',
adminonly: true
},
twvoy: {
label: conv({ hans: '转移至维基导游', hant: '轉移至維基導遊' }),
action: 'noop',
adminonly: true
},
two: {
label: conv({ hans: '转移至其他维基计划', hant: '轉移至其他維基計劃' }),
action: 'noop',
adminonly: true
}
}
},
{
key: conv({ hans: '其他处理方法', hant: '其他處理方法' }),
value: {
relist: {
label: conv({ hans: '重新提交讨论', hant: '重新提交討論' }),
action: 'noop',
disabled: mw.config.get('wgPageName') === 'Wikipedia:頁面存廢討論/記錄/' + date.format('YYYY/MM/DD', 'utc'),
hidden: !/^Wikipedia:頁面存廢討論\/記錄\//.test(mw.config.get('wgPageName'))
},
c: {
label: conv({ hans: '转交侵权', hant: '轉交侵權' }),
action: 'noop'
},
m2ifd: {
label: conv({ hans: '转送文件存废讨论', hant: '轉送檔案存廢討論' }),
action: 'noop'
},
r: {
label: '重定向',
action: 'keep',
adminonly: true
},
cr: {
label: conv({ hans: '分类重定向', hant: '分類重定向' }),
action: 'keep',
adminonly: true
},
m: {
label: conv({ hans: '移动', hant: '移動' }),
action: 'keep',
adminonly: true
},
merge: {
label: conv({ hans: '并入', hant: '併入' }),
action: 'keep',
adminonly: true
},
mergeapproved: {
label: conv({ hans: '允许并入', hant: '允許併入' }),
action: 'keep',
adminonly: true
},
nc: {
label: conv({ hans: '无共识暂时保留', hant: '無共識暫時保留' }),
value: conv({ hans: '无共识', hant: '無共識' }),
action: 'keep'
}
}
}];
Twinkle.close.callback = function twinklecloseCallback(title, section, parentSection, noop) {
var Window = new Morebits.simpleWindow(410, 200);
Window.setTitle(conv({ hans: '关闭存废讨论', hant: '關閉存廢討論' }) + ' \u00B7 ' + title);
Window.setScriptName('Twinkle');
Window.addFooterLink(conv({ hans: '存废讨论设置', hant: '存廢討論設定' }), 'WP:TW/PREF#close');
Window.addFooterLink(conv({ hans: 'Twinkle帮助', hant: 'Twinkle說明' }), 'WP:TW/DOC#close');
var form = new Morebits.quickForm(Twinkle.close.callback.evaluate);
if ($('.skin-vector-2022').length > 0) {
mw.notify(conv({ hans: '关闭存废讨论功能暂不支持 Vector 2022,请改用其他外观。', hant: '關閉存廢討論功能暫不支援 Vector 2022,請改用其他外觀。' }), { type: 'error' });
form.append({
type: 'div',
label: conv({ hans: '关闭存废讨论功能暂不支持 Vector 2022,请改用其他外观。', hant: '關閉存廢討論功能暫不支援 Vector 2022,請改用其他外觀。' })
});
var result2 = form.render();
Window.setContent(result2);
Window.display();
return;
}
form.append({
type: 'select',
label: conv({ hans: '处理结果:', hant: '處理結果:' }),
name: 'sub_group',
event: Twinkle.close.callback.change_code
});
form.append({
type: 'input',
name: 'sdreason',
label: conv({ hans: '速删理由:', hant: '速刪理由:' }),
tooltip: conv({ hans: '用于删除日志,使用{{delete}}的参数格式,例如 A1 或 A1|G1', hant: '用於刪除日誌,使用{{delete}}的參數格式,例如 A1 或 A1|G1' }),
hidden: true
});
form.append({
type: 'input',
name: 'remark',
label: conv({ hans: '补充说明:', hant: '補充說明:' })
});
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '只关闭讨论,不进行其他操作', hant: '只關閉討論,不進行其他操作' }),
value: 'noop',
name: 'noop',
event: Twinkle.close.callback.change_operation,
checked: noop
}
]
});
if (new mw.Title(title).namespace % 2 === 0 && new mw.Title(title).namespace !== 2) { // hide option for user pages, to avoid accidentally deleting user talk page
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除关联的讨论页', hant: '刪除關聯的討論頁' }),
value: 'talkpage',
name: 'talkpage',
tooltip: conv({ hans: '删除时附带删除此页面的讨论页。', hant: '刪除時附帶刪除此頁面的討論頁。' }),
checked: true,
event: function(event) {
event.stopPropagation();
}
}
]
});
}
form.append({
type: 'checkbox',
list: [
{
label: conv({ hans: '删除重定向页', hant: '刪除重新導向頁面' }),
value: 'redirects',
name: 'redirects',
tooltip: conv({ hans: '删除到此页的重定向。', hant: '刪除到此頁的重新導向。' }),
checked: true,
event: function(event) {
event.stopPropagation();
}
}
]
});
form.append({ type: 'submit' });
var result = form.render();
Window.setContent(result);
Window.display();
var sub_group = result.getElementsByTagName('select')[0]; // hack
var resultData = {
title: title,
section: parseInt(section),
parentSection: parseInt(parentSection),
noop: noop
};
$(result).data('resultData', resultData);
// worker function to create the combo box entries
var createEntries = function(contents, container) {
$.each(contents, function(itemKey, itemProperties) {
var key = typeof itemKey === 'string' ? itemKey : itemProperties.value;
var elem = new Morebits.quickForm.element({
type: 'option',
label: key + ':' + itemProperties.label,
value: key,
selected: itemProperties.selected,
disabled: (Twinkle.getPref('XfdClose') !== 'all' && itemProperties.adminonly) || itemProperties.disabled,
hidden: itemProperties.hidden
});
var elemRendered = container.appendChild(elem.render());
$(elemRendered).data('messageData', itemProperties);
});
};
Twinkle.close.codes.forEach(function(group) {
var optgroup = new Morebits.quickForm.element({
type: 'optgroup',
label: group.key
});
optgroup = optgroup.render();
sub_group.appendChild(optgroup);
// create the options
createEntries(group.value, optgroup);
});
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.sub_group.dispatchEvent(evt);
};
Twinkle.close.callback.change_operation = function twinklecloseCallbackChangeOperation(e) {
var noop = e.target.checked;
var code = e.target.form.sub_group.value;
var messageData = $(e.target.form.sub_group).find('option[value="' + code + '"]').data('messageData');
var talkpage = e.target.form.talkpage;
var redirects = e.target.form.redirects;
if (noop || messageData.action === 'keep') {
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
if (talkpage) {
talkpage.checked = true;
talkpage.disabled = false;
}
redirects.checked = true;
redirects.disabled = false;
}
};
Twinkle.close.callback.change_code = function twinklecloseCallbackChangeCode(e) {
var resultData = $(e.target.form).data('resultData');
var messageData = $(e.target).find('option[value="' + e.target.value + '"]').data('messageData');
var noop = e.target.form.noop;
var talkpage = e.target.form.talkpage;
var redirects = e.target.form.redirects;
if (resultData.noop || messageData.action === 'noop') {
noop.checked = true;
noop.disabled = true;
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
noop.checked = false;
noop.disabled = false;
if (messageData.action === 'keep') {
if (talkpage) {
talkpage.checked = false;
talkpage.disabled = true;
}
redirects.checked = false;
redirects.disabled = true;
} else {
if (talkpage) {
talkpage.checked = true;
talkpage.disabled = false;
}
redirects.checked = true;
redirects.disabled = false;
}
if (e.target.value === 'sd') {
e.target.form.sdreason.parentElement.removeAttribute('hidden');
} else {
e.target.form.sdreason.parentElement.setAttribute('hidden', '');
}
}
};
Twinkle.close.callback.evaluate = function twinklecloseCallbackEvaluate(e) {
var code = e.target.sub_group.value;
var resultData = $(e.target).data('resultData');
var messageData = $(e.target.sub_group).find('option[value="' + code + '"]').data('messageData');
var noop = e.target.noop.checked;
var talkpage = e.target.talkpage && e.target.talkpage.checked;
var redirects = e.target.redirects.checked;
var params = {
title: resultData.title,
code: code,
remark: e.target.remark.value,
sdreason: e.target.sdreason.value,
section: resultData.section,
parentSection: resultData.parentSection,
messageData: messageData,
talkpage: talkpage,
redirects: redirects
};
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(e.target);
Morebits.wiki.actionCompleted.notice = '操作完成';
if (noop || messageData.action === 'noop') {
Twinkle.close.callbacks.talkend(params);
} else {
switch (messageData.action) {
case 'del':
Twinkle.close.callbacks.del(params);
break;
case 'keep':
var wikipedia_page = new Morebits.wiki.page(params.title, conv({ hans: '移除存废讨论模板', hant: '移除存廢討論模板' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.close.callbacks.keep);
break;
default:
alert('Twinkle.close:未定义 ' + code);
}
}
};
Twinkle.close.callbacks = {
del: function (params) {
var query, wikipedia_api;
Morebits.wiki.addCheckpoint();
var page = new Morebits.wiki.page(params.title, conv({ hans: '删除页面', hant: '刪除頁面' }));
if (params.code === 'sd') {
Twinkle.speedy.callbacks.parseWikitext(params.title, '{{delete|' + params.sdreason + '}}', function(reason) {
reason = prompt(conv({ hans: '输入删除理由,或点击确定以接受自动生成的:', hant: '輸入刪除理由,或點選確定以接受自動生成的:' }), reason);
if (reason === null) {
page.getStatusElement().warn(conv({ hans: '没有执行删除', hant: '沒有執行刪除' }));
Twinkle.close.callbacks.talkend(params);
} else {
page.setEditSummary(reason);
page.setChangeTags(Twinkle.changeTags);
page.deletePage(function() {
page.getStatusElement().info('完成');
Twinkle.close.callbacks.talkend(params);
});
}
});
} else {
page.setEditSummary(conv({ hans: '存废讨论通过:[[', hant: '存廢討論通過:[[' }) + mw.config.get('wgPageName') + '#' + params.title + ']]');
page.setChangeTags(Twinkle.changeTags);
page.deletePage(function() {
page.getStatusElement().info('完成');
Twinkle.close.callbacks.talkend(params);
});
}
if (params.redirects) {
query = {
action: 'query',
titles: params.title,
prop: 'redirects',
rdlimit: 'max' // 500 is max for normal users, 5000 for bots and sysops
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在获取重定向', hant: '正在取得重新導向' }), query, Twinkle.close.callbacks.deleteRedirectsMain);
wikipedia_api.params = params;
wikipedia_api.post();
}
if (params.talkpage) {
var pageTitle = mw.Title.newFromText(params.title);
if (pageTitle && pageTitle.namespace % 2 === 0 && pageTitle.namespace !== 2) {
pageTitle.namespace++; // now pageTitle is the talk page title!
query = {
action: 'query',
titles: pageTitle.toText()
};
wikipedia_api = new Morebits.wiki.api(conv({ hans: '正在检查讨论页面是否存在', hant: '正在檢查討論頁面是否存在' }), query, Twinkle.close.callbacks.deleteTalk);
wikipedia_api.params = params;
wikipedia_api.params.talkPage = pageTitle.toText();
wikipedia_api.post();
}
}
Morebits.wiki.removeCheckpoint();
},
deleteRedirectsMain: function(apiobj) {
var xml = apiobj.responseXML;
var pages = $(xml).find('rd').map(function() {
return $(this).attr('title');
}).get();
if (!pages.length) {
return;
}
var redirectDeleter = new Morebits.batchOperation(conv({ hans: '正在删除到 ', hant: '正在刪除到 ' }) + apiobj.params.title + conv({ hans: ' 的重定向', hant: ' 的重新導向' }));
redirectDeleter.setOption('chunkSize', Twinkle.getPref('batchdeleteChunks'));
redirectDeleter.setPageList(pages);
redirectDeleter.run(function(pageName) {
var wikipedia_page = new Morebits.wiki.page(pageName, conv({ hans: '正在删除 ', hant: '正在刪除 ' }) + pageName);
wikipedia_page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '指向已删页面“', hant: '指向已刪頁面「' }) + apiobj.params.title + conv({ hans: '”的重定向', hant: '」的重新導向' }));
wikipedia_page.setChangeTags(Twinkle.changeTags);
wikipedia_page.deletePage(redirectDeleter.workerSuccess, redirectDeleter.workerFailure);
});
},
deleteTalk: function(apiobj) {
var xml = apiobj.responseXML;
var exists = $(xml).find('page:not([missing])').length > 0;
if (!exists) {
// no talk page; forget about it
return;
}
var page = new Morebits.wiki.page(apiobj.params.talkPage, conv({ hans: '正在删除页面 ', hant: '正在刪除頁面 ' }) + apiobj.params.title + conv({ hans: ' 的讨论页', hant: ' 的討論頁' }));
page.setEditSummary('[[WP:CSD#G15|G15]]: ' + conv({ hans: '已删页面“', hant: '已刪頁面「' }) + apiobj.params.title + conv({ hans: '”的[[Wikipedia:讨论页|讨论页]]', hant: '」的[[Wikipedia:討論頁|討論頁]]' }));
page.setChangeTags(Twinkle.changeTags);
page.deletePage();
},
keep: function (pageobj) {
var statelem = pageobj.getStatusElement();
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var pagetitle = mw.Title.newFromText(params.title);
if (pagetitle.getNamespaceId() % 2 === 0) {
var talkpagetitle = new mw.Title(pagetitle.getMainText(), pagetitle.getNamespaceId() + 1);
var talkpage = new Morebits.wiki.page(talkpagetitle.toString(), conv({ hans: '标记讨论页', hant: '標記討論頁' }));
var reason = params.messageData.value || params.messageData.label;
var vfdkept = '{{Old vfd multi|' + mw.config.get('wgPageName').split('/').slice(2).join('/') + '|' + reason + '}}\n';
talkpage.setPrependText(vfdkept);
talkpage.setEditSummary('[[' + mw.config.get('wgPageName') + '#' + params.title + ']]:' + reason);
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setCreateOption('recreate');
talkpage.prepend();
}
var newtext = text.replace(/<noinclude>\s*\{\{([rsaiftcmv]fd)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*<\/noinclude>\s*/gi, '');
newtext = newtext.replace(/\{\{([rsaiftcmv]fd)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/gi, '');
if (params.code !== 'tk') {
newtext = newtext.replace(/\{\{(notability|fame|mair|知名度|重要性|显著性|顯著性|知名度不足|人物重要性|重要性不足|notable|关注度|关注度不足|關注度|關注度不足|重要|重要度)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\n*/gi, '');
newtext = newtext.replace(/\{\{(substub|小小作品|cod|小小條目|小小条目)(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\n*/gi, '');
}
if (params.code === 'mergeapproved') {
var tag = '{{subst:Merge approved/auto|discuss=' + mw.config.get('wgPageName') + '#' + params.title + '}}\n';
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(newtext);
newtext = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
if (newtext === text) {
statelem.warn(conv({ hans: '未找到存废讨论模板,可能已被移除', hant: '未找到存廢討論模板,可能已被移除' }));
Twinkle.close.callbacks.talkend(params);
return;
}
var editsummary = conv({ hans: '存废讨论关闭:[[', hant: '存廢討論關閉:[[' }) + mw.config.get('wgPageName') + '#' + params.title + ']]';
pageobj.setPageText(newtext);
pageobj.setEditSummary(editsummary);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.close.callbacks.keepComplete);
},
keepComplete: function (pageobj) {
var params = pageobj.getCallbackParameters();
Twinkle.close.callbacks.talkend(params);
},
talkend: function (params) {
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), conv({ hans: '关闭讨论', hant: '關閉討論' }));
wikipedia_page.setCallbackParameters(params);
wikipedia_page.setPageSection(params.section);
wikipedia_page.load(Twinkle.close.callbacks.saveTalk);
},
saveTalk: function (pageobj) {
var statelem = pageobj.getStatusElement();
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
if (text.indexOf('{{delh') !== -1) {
statelem.error(conv({ hans: '讨论已被关闭', hant: '討論已被關閉' }));
return;
}
var sbegin = text.indexOf('<section begin=backlog />') !== -1;
var send = text.indexOf('<section end=backlog />') !== -1;
text = text.replace('\n<section begin=backlog />', '');
text = text.replace('\n<section end=backlog />', '');
var bar = text.split('\n----\n');
var split = bar[0].split('\n');
text = split[0] + '\n{{delh|' + params.code + '}}\n';
var reason;
if (params.code === 'relist') {
var dateStr = new Morebits.date().format('YYYY/MM/DD', 'utc');
var logtitle = 'Wikipedia:頁面存廢討論/記錄/' + dateStr;
text += '{{Relisted}}到[[' + logtitle + '#' + params.title + ']]。';
reason = '重新提交到[[' + logtitle + '#' + params.title + '|' + dateStr + ']]';
split[0] = split[0].replace(/^===(.+)===$/, '==$1==');
var relist_params = {
title: params.title,
source: pageobj.getPageName(),
text: split.join('\n'),
comment: params.remark
};
var logpage = new Morebits.wiki.page(logtitle, '重新提交');
if (params.parentSection > 0) {
Morebits.status.info(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '正在获取批量提删理据…', hant: '正在取得批量提刪理據…' }));
var api = new mw.Api();
api.get({
action: 'query',
format: 'json',
prop: 'revisions',
titles: pageobj.getPageName(),
formatversion: 2,
rvprop: 'content',
rvsection: params.parentSection
}).then(function (data) {
var content = data.query.pages[0].revisions[0].content;
relist_params.batchText = content;
logpage.setCallbackParameters(relist_params);
logpage.load(Twinkle.close.callbacks.relistToday);
});
} else {
logpage.setCallbackParameters(relist_params);
logpage.load(Twinkle.close.callbacks.relistToday);
}
var article_params = {
date: dateStr
};
var articlepage = new Morebits.wiki.page(params.title, conv({ hans: '重新标记', hant: '重新標記' }));
articlepage.setCallbackParameters(article_params);
articlepage.load(Twinkle.close.callbacks.retaggingArticle);
} else {
text += split.slice(1).join('\n');
reason = params.messageData.value || params.messageData.label;
text += '\n<hr>\n: ' + reason;
if (params.remark) {
text += ':' + Morebits.string.appendPunctuation(params.remark);
} else {
text += '。';
}
}
if (!Morebits.userIsSysop) {
text += '{{subst:NAC}}';
}
text += '--~~~~\n{{delf}}';
if (bar[1]) {
text += '\n----\n' + bar.slice(1).join('\n----\n');
}
if (send) {
text += '\n<section end=backlog />';
}
if (sbegin) {
// guaranteed to be at tne end?
text += '\n<section begin=backlog />';
}
pageobj.setPageText(text);
pageobj.setEditSummary('/* ' + params.title + ' */ ' + reason);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('nocreate');
pageobj.save(Twinkle.close.callbacks.disableLink);
},
relistToday: function (pageobj) {
var params = pageobj.getCallbackParameters();
var lines = params.text.replace(/<!-- Twinkle:.+-->\n?/, '').trim().split('\n');
var appendText = '\n{{safesubst:SafeAfdHead}}\n' + lines[0] + '\n';
if (params.batchText) {
var bar = params.batchText.split('\n----\n');
var comment = bar[bar.length - 1];
var m = comment.match(/({{[删刪]除}}理據.*)\n(提[报報]以上.*)/);
if (m) {
appendText += m[1] + '\n: ' + m[2] + '\n';
} else {
Morebits.status.warn(conv({ hans: '信息', hant: '資訊' }), conv({ hans: '无法解析批量提删理据', hant: '無法解析批量提刪理據' }));
}
}
appendText += lines.slice(1).join('\n') + '\n{{subst:Relist';
if (params.comment) {
appendText += '|1=' + params.comment;
}
appendText += '}}';
var sourceAnchor = params.source + '#' + params.title;
var dateStr = params.source.replace('Wikipedia:頁面存廢討論/記錄/', '');
pageobj.setAppendText(appendText);
pageobj.setEditSummary('/* ' + params.title + ' */ 重新提交自[[' + sourceAnchor + '|' + dateStr + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.append();
},
retaggingArticle: function (pageobj) {
var statelem = pageobj.getStatusElement();
// defaults to /doc for lua modules, which may not exist
if (!pageobj.exists()) {
statelem.error(conv({ hans: '页面不存在,可能已被删除', hant: '頁面不存在,可能已被刪除' }));
return;
}
var params = pageobj.getCallbackParameters();
var text = pageobj.getPageText();
if (/{{[rsaiftcmv]fd\s*(\|.*)?\|\s*date\s*=[^|}]*.*}}/.test(text)) {
text = text.replace(/({{[rsaiftcmv]fd\s*(?:\|.*)?\|\s*date\s*=)[^|}]*(.*}})/, '$1' + params.date + '$2');
} else {
Morebits.status.warn(conv({ hans: '重新标记', hant: '重新標記' }), conv({ hans: '找不到提删模板,重新插入', hant: '找不到提刪模板,重新插入' }));
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
var tag = '{{vfd|date=' + params.date + '}}\n';
text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
}
pageobj.setPageText(text);
pageobj.setEditSummary('重新提交到[[Wikipedia:頁面存廢討論/記錄/' + params.date + '#' + pageobj.getPageName() + ']]');
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.save();
},
disableLink: function (pageobj) {
var params = pageobj.getCallbackParameters();
$('a.twinkle-close-button[data-section=' + params.section + ']').addClass('twinkle-close-button-disabled');
}
};
Twinkle.addInitCallback(Twinkle.close, 'close');
})(jQuery);
// </nowiki>
8c30fb07a797742217eb55db56605bdc355530a0
MediaWiki:Gadget-twinkleconfig.js
8
169
341
340
2024-08-03T04:07:32Z
黑茶
2
导入1个版本
javascript
text/javascript
// <nowiki>
(function($) {
/*
****************************************
*** twinkleconfig.js: Preferences module
****************************************
* Mode of invocation: Adds configuration form to Wikipedia:Twinkle/Preferences,
and adds an ad box to the top of user subpages belonging to the
currently logged-in user which end in '.js'
* Active on: What I just said. Yeah.
I, [[User:This, that and the other]], originally wrote this. If the code is misbehaving, or you have any
questions, don't hesitate to ask me. (This doesn't at all imply [[WP:OWN]]ership - it's just meant to
point you in the right direction.) -- TTO
*/
var conv = require('ext.gadget.HanAssist').conv;
Twinkle.config = {};
Twinkle.config.watchlistEnums = {
'yes': conv({ hans: '永久加入到监视列表', hant: '永久加入到監視清單' }),
'no': conv({ hans: '不加入到监视列表', hant: '不加入到監視清單' }),
'default': conv({ hans: '遵守站点设置', hant: '遵守站點設定' }),
'1 week': conv({ hans: '加入到监视列表1周', hant: '加入到監視清單1週' }),
'1 month': conv({ hans: '加入到监视列表1个月', hant: '加入到監視清單1個月' }),
'3 months': conv({ hans: '加入到监视列表3个月', hant: '加入到監視清單3個月' }),
'6 months': conv({ hans: '加入到监视列表6个月', hant: '加入到監視清單6個月' })
};
Twinkle.config.commonSets = {
csdCriteria: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdCriteriaDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
csdCriteriaNotification: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdCriteriaNotificationDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
csdAndDICriteria: {
db: conv({ hans: '自定义理由', hant: '自訂理由' }),
g1: 'G1', g2: 'G2', g3: 'G3', g5: 'G5', g10: 'G10', g11: 'G11', g12: 'G12', g13: 'G13', g14: 'G14', g15: 'G15', g16: 'G16',
a1: 'A1', a2: 'A2', a3: 'A3', a5: 'A5', a6: 'A6',
o1: 'O1', o3: 'O3', o4: 'O4', o7: 'O7', o8: 'O8',
f1: 'F1', f3: 'F3', f4: 'F4', f5: 'F5', f6: 'F6', f7: 'F7', f8: 'F8', f9: 'F9', f10: 'F10',
r2: 'R2', r3: 'R3', r5: 'R5', r6: 'R6', r7: 'R7', r8: 'R8'
},
csdAndDICriteriaDisplayOrder: [
'db',
'g1', 'g2', 'g3', 'g5', 'g10', 'g11', 'g12', 'g13', 'g14', 'g15', 'g16',
'a1', 'a2', 'a3', 'a5', 'a6',
'o1', 'o3', 'o4', 'o7', 'o8',
'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10',
'r2', 'r3', 'r5', 'r6', 'r7', 'r8'
],
xfdCriteria: {
delete: conv({ hans: '删除', hant: '刪除' }), merge: conv({ hans: '合并', hant: '合併' }),
vmd: conv({ hans: '移动到维基词典', hant: '移動到維基詞典' }), vms: conv({ hans: '移动到维基文库', hant: '移動到維基文庫' }), vmb: conv({ hans: '移动到维基教科书', hant: '移動到維基教科書' }), vmq: conv({ hans: '移动到维基语录', hant: '移動到維基語錄' }), vmvoy: conv({ hans: '移动到维基导游', hant: '移動到維基導遊' }), vmv: conv({ hans: '移动到维基学院', hant: '移動到維基學院' }),
fwdcsd: conv({ hans: '转交自快速删除候选', hant: '轉交自快速刪除候選' }),
fame: conv({ hans: '批量关注度提删', hant: '批次關注度提刪' }), substub: conv({ hans: '批量小小作品提删', hant: '批次小小作品提刪' }), batch: conv({ hans: '批量其他提删', hant: '批次其他提刪' }),
ffd: conv({ hans: '文件存废讨论', hant: '檔案存廢討論' })
},
xfdCriteriaDisplayOrder: [
'delete', 'merge',
'vmd', 'vms', 'vmb', 'vmq', 'vmvoy', 'vmv',
'fwdcsd',
'fame', 'substub', 'batch',
'ffd'
],
namespacesNoSpecial: {
0: conv({ hans: '(条目)', hant: '(條目)' }),
1: 'Talk',
2: 'User',
3: 'User talk',
4: 'Wikipedia',
5: 'Wikipedia talk',
6: 'File',
7: 'File talk',
8: 'MediaWiki',
9: 'MediaWiki talk',
10: 'Template',
11: 'Template talk',
12: 'Help',
13: 'Help talk',
14: 'Category',
15: 'Category talk',
100: 'Portal',
101: 'Portal talk',
102: 'WikiProject',
103: 'WikiProject talk',
118: 'Draft',
119: 'Draft talk',
828: 'Module',
829: 'Module talk'
}
};
/**
* Section entry format:
*
* {
* title: <human-readable section title>,
* module: <name of the associated module, used to link to sections>,
* adminOnly: <true for admin-only sections>,
* hidden: <true for advanced preferences that rarely need to be changed - they can still be modified by manually editing twinkleoptions.js>,
* preferences: [
* {
* name: <TwinkleConfig property name>,
* label: <human-readable short description - used as a form label>,
* helptip: <(optional) human-readable text (using valid HTML) that complements the description, like limits, warnings, etc.>
* adminOnly: <true for admin-only preferences>,
* type: <string|boolean|integer|enum|set|customList> (customList stores an array of JSON objects { value, label }),
* enumValues: <for type = "enum": a JSON object where the keys are the internal names and the values are human-readable strings>,
* setValues: <for type = "set": a JSON object where the keys are the internal names and the values are human-readable strings>,
* setDisplayOrder: <(optional) for type = "set": an array containing the keys of setValues (as strings) in the order that they are displayed>,
* customListValueTitle: <for type = "customList": the heading for the left "value" column in the custom list editor>,
* customListLabelTitle: <for type = "customList": the heading for the right "label" column in the custom list editor>
* },
* . . .
* ]
* },
* . . .
*
*/
Twinkle.config.sections = [
{
title: conv({ hans: '常规', hant: '常規' }),
module: 'general',
preferences: [
// TwinkleConfig.userTalkPageMode may take arguments:
// 'window': open a new window, remember the opened window
// 'tab': opens in a new tab, if possible.
// 'blank': force open in a new window, even if such a window exists
{
name: 'userTalkPageMode',
label: conv({ hans: '当要打开用户讨论页时', hant: '當要打開使用者討論頁時' }),
type: 'enum',
enumValues: {
window: conv({ hans: '在窗口中,替换成其它用户对话页', hant: '在當前分頁,替換成其它用戶討論頁' }),
tab: conv({ hans: '在新标签页中', hant: '在新分頁中' }),
blank: conv({ hans: '在全新的窗口中', hant: '在新視窗中' })
}
},
// TwinkleConfig.dialogLargeFont (boolean)
{
name: 'dialogLargeFont',
label: conv({ hans: '在Twinkle对话框中使用大号字体', hant: '在Twinkle對話方塊中使用大號字型' }),
type: 'boolean'
},
// Twinkle.config.disabledModules (array)
{
name: 'disabledModules',
label: conv({ hans: '关闭指定的Twinkle模块', hant: '關閉指定的Twinkle模組' }),
helptip: conv({ hans: '您在此选择的功能将无法使用,取消选择以重新启用功能。', hant: '您在此選擇的功能將無法使用,取消選擇以重新啟用功能。' }),
type: 'set',
setValues: { arv: conv({ hans: '告状', hant: '告狀' }), warn: '警告', block: conv({ hans: '封禁', hant: '封鎖' }), welcome: conv({ hans: '欢迎', hant: '歡迎' }), talkback: '通告', speedy: conv({ hans: '速删', hant: '速刪' }), copyvio: conv({ hans: '侵权', hant: '侵權' }), xfd: conv({ hans: '提删', hant: '提刪' }), image: conv({ hans: '图权', hant: '圖權' }), protect: conv({ hans: '保护', hant: '保護' }), tag: conv({ hans: '标记', hant: '標記' }), stub: '小作品', diff: conv({ hans: '差异', hant: '差異' }), unlink: conv({ hans: '链入', hant: '連入' }), fluff: '回退' }
},
// Twinkle.config.disabledSysopModules (array)
{
name: 'disabledSysopModules',
label: conv({ hans: '关闭指定的Twinkle管理员模块', hant: '關閉指定的Twinkle管理員模組' }),
helptip: conv({ hans: '您在此选择的功能将无法使用,取消选择以重新启用功能。', hant: '您在此選擇的功能將無法使用,取消選擇以重新啟用功能。' }),
adminOnly: true,
type: 'set',
setValues: { batchdelete: conv({ hans: '批删', hant: '批刪' }), batchundelete: conv({ hans: '批复', hant: '批復' }) }
}
]
},
{
title: conv({ hans: '告状', hant: '告狀' }),
module: 'arv',
preferences: [
{
name: 'spiWatchReport',
label: conv({ hans: '发起傀儡调查时加入到监视列表', hant: '發起傀儡調查時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: conv({ hans: '封禁用户', hant: '封鎖使用者' }),
module: 'block',
adminOnly: true,
preferences: [
// TwinkleConfig.defaultToBlock64 (boolean)
// Whether to default to just blocking the /64 on or off
{
name: 'defaultToBlock64',
label: conv({ hans: '对于IPv6地址,默认选择封禁/64段', hant: '對於IPv6地址,預設選擇封鎖/64段' }),
type: 'boolean'
},
// TwinkleConfig.defaultToPartialBlocks (boolean)
// Whether to default partial blocks on or off
{
name: 'defaultToPartialBlocks',
label: conv({ hans: '打开封禁菜单时默认选择部分封禁', hant: '打開封鎖選單時預設選擇部分封鎖' }),
type: 'boolean'
},
// TwinkleConfig.watchBlockNotices (string)
// Watchlist setting for the page which has been dispatched an warning or notice
{
name: 'watchBlockNotices',
label: conv({ hans: '发送封禁模板时加入用户讨论页到监视列表', hant: '發送封鎖模板時加入使用者討論頁到監視清單' }),
helptip: conv({ hans: '注意:如果对方使用Flow,对应讨论串总会加到监视列表中。', hant: '注意:如果對方使用Flow,對應討論串總會加到監視清單中。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'customBlockReasonList',
label: conv({ hans: '自定义封禁理由', hant: '自訂封鎖理由' }),
helptip: conv({ hans: '您可以加入常用的封禁理由。自定义的封禁理由会出现在一般的封禁理由下方。', hant: '您可以加入常用的封鎖理由。自訂的封鎖理由會出現在一般的封鎖理由下方。' }),
type: 'customList',
customListValueTitle: conv({ hans: '使用封禁模板(默认为 uw-block1)', hant: '使用封鎖模板(預設為 uw-block1)' }),
customListLabelTitle: conv({ hans: '“由于…您已被封禁”及封禁日志理由', hant: '「由於…您已被封鎖」及封鎖日誌理由' })
}
]
},
{
title: conv({ hans: '图片删除', hant: '圖片刪除' }),
module: 'image',
preferences: [
// TwinkleConfig.notifyUserOnDeli (boolean)
// If the user should be notified after placing a file deletion tag
{
name: 'notifyUserOnDeli',
label: conv({ hans: '默认勾选“通知创建者”', hant: '預設勾選「通知建立者」' }),
type: 'boolean'
},
// TwinkleConfig.deliWatchPage (string)
// The watchlist setting of the page tagged for deletion.
{
name: 'deliWatchPage',
label: conv({ hans: '标记图片时加入到监视列表', hant: '標記圖片時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.deliWatchUser (string)
// The watchlist setting of the user talk page if a notification is placed.
{
name: 'deliWatchUser',
label: conv({ hans: '标记图片时加入创建者讨论页到监视列表', hant: '標記圖片時加入建立者討論頁到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: conv({ hans: '保护', hant: '保護' }),
module: 'protect',
preferences: [
{
name: 'watchRequestedPages',
label: conv({ hans: '请求保护页面时加入到监视列表', hant: '請求保護頁面時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchPPTaggedPages',
label: conv({ hans: '标记保护模板时加入到监视列表', hant: '標記保護模板時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchProtectedPages',
label: conv({ hans: '保护时加入到监视列表', hant: '保護時加入到監視清單' }),
helptip: conv({ hans: '如果在保护后也标记页面,则使用标记页面的参数设置。', hant: '如果在保護後也標記頁面,則使用標記頁面的偏好設定。' }),
adminOnly: true,
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
}
]
},
{
title: '回退', // twinklefluff module
module: 'fluff',
preferences: [
// TwinkleConfig.autoMenuAfterRollback (bool)
// Option to automatically open the warning menu if the user talk page is opened post-reversion
{
name: 'autoMenuAfterRollback',
label: conv({ hans: '在Twinkle回退后自动打开用户讨论页上的Twinkle警告菜单', hant: '在Twinkle回退後自動打開使用者討論頁上的Twinkle警告選單' }),
helptip: conv({ hans: '仅在选取下方对应框时才执行', hant: '僅在選取下方對應框時才執行' }),
type: 'boolean'
},
// TwinkleConfig.openTalkPage (array)
// What types of actions that should result in opening of talk page
{
name: 'openTalkPage',
label: conv({ hans: '在这些类型的回退后打开用户讨论页', hant: '在這些類別的回退後打開使用者討論頁' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }) }
},
// TwinkleConfig.openTalkPageOnAutoRevert (bool)
// Defines if talk page should be opened when calling revert from contribs or recent changes pages. If set to true, openTalkPage defines then if talk page will be opened.
{
name: 'openTalkPageOnAutoRevert',
label: conv({ hans: '在从用户贡献及最近更改中发起回退时打开用户讨论页', hant: '在從使用者貢獻及近期變更中發起回退時打開使用者討論頁' }),
helptip: conv({ hans: '当它打开时,依赖上一个设置。', hant: '當它打開時,依賴上一個設定。' }),
type: 'boolean'
},
// TwinkleConfig.rollbackInPlace (bool)
//
{
name: 'rollbackInPlace',
label: conv({ hans: '在从用户贡献及最近更改中发起回退时不刷新页面', hant: '在從使用者貢獻及近期變更中發起回退時不重新整理頁面' }),
helptip: conv({ hans: '当它打开时,Twinkle将不会在从用户贡献及最近更改中发起回退时刷新页面,允许您一次性回退多个编辑。', hant: '當它打開時,Twinkle將不會在從使用者貢獻及近期變更中發起回退時重新整理頁面,允許您一次性回退多個編輯。' }),
type: 'boolean'
},
// TwinkleConfig.markRevertedPagesAsMinor (array)
// What types of actions that should result in marking edit as minor
{
name: 'markRevertedPagesAsMinor',
label: conv({ hans: '将这些类型的回退标记为小修改', hant: '將這些類別的回退標記為小修改' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }), torev: conv({ hans: '“恢复此版本”', hant: '「恢復此版本」' }) }
},
// TwinkleConfig.watchRevertedPages (array)
// What types of actions that should result in forced addition to watchlist
{
name: 'watchRevertedPages',
label: conv({ hans: '把这些类型的回退加入到监视列表', hant: '把這些類別的回退加入到監視清單' }),
type: 'set',
setValues: { agf: '善意回退', norm: conv({ hans: '常规回退', hant: '常規回退' }), vand: conv({ hans: '破坏回退', hant: '破壞回退' }), torev: conv({ hans: '“恢复此版本”', hant: '「恢復此版本」' }) }
},
// TwinkleConfig.watchRevertedExpiry
// If any of the above items are selected, whether to expire the watch
{
name: 'watchRevertedExpiry',
label: conv({ hans: '当回退页面时,加入到监视列表的期限', hant: '當回退頁面時,加入到監視清單的期限' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.offerReasonOnNormalRevert (boolean)
// If to offer a prompt for extra summary reason for normal reverts, default to true
{
name: 'offerReasonOnNormalRevert',
label: conv({ hans: '常规回退时询问理由', hant: '常規回退時詢問理由' }),
helptip: conv({ hans: '“常规”回退是中间的那个[回退]链接。', hant: '「常規」回退是中間的那個[回退]連結。' }),
type: 'boolean'
},
{
name: 'confirmOnFluff',
label: conv({ hans: '回退前要求确认(所有设备)', hant: '回退前要求確認(所有裝置)' }),
helptip: conv({ hans: '对于使用移动设备的用户,或者意志不坚定的。', hant: '對於使用行動裝置的使用者,或者意志不堅定的。' }),
type: 'boolean'
},
{
name: 'confirmOnMobileFluff',
label: conv({ hans: '回退前要求确认(仅移动设备)', hant: '回退前要求確認(僅行動裝置)' }),
helptip: conv({ hans: '避免在移动设备意外执行回退。', hant: '避免在行動裝置意外執行回退。' }),
type: 'boolean'
},
// TwinkleConfig.showRollbackLinks (array)
// Where Twinkle should show rollback links:
// diff, others, mine, contribs, history, recent
// Note from TTO: |contribs| seems to be equal to |others| + |mine|, i.e. redundant, so I left it out heres
{
name: 'showRollbackLinks',
label: conv({ hans: '在这些页面上显示回退链接', hant: '在這些頁面上顯示回退連結' }),
type: 'set',
setValues: { diff: conv({ hans: '差异', hant: '差異' }), history: conv({ hans: '历史记录', hant: '歷史記錄' }), others: conv({ hans: '其它用户的贡献', hant: '其它使用者的貢獻' }), mine: conv({ hans: '我的贡献', hant: '我的貢獻' }), recentchanges: conv({ hans: '最近更改', hant: '近期變更' }), recentchangeslinked: conv({ hans: '相关更改', hant: '相關變更' }) }
},
{
name: 'customRevertSummary',
label: '回退理由',
helptip: conv({ hans: '在查看差异时可选,仅善意回退、常规回退、恢复此版本', hant: '在檢視差異時可選,僅善意回退、常規回退、恢復此版本' }),
type: 'customList',
customListValueTitle: '理由',
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: conv({ hans: '共享IP标记', hant: '共享IP標記' }),
module: 'shared',
preferences: [
{
name: 'markSharedIPAsMinor',
label: conv({ hans: '将共享IP标记标记为小修改', hant: '將共享IP標記標記為小修改' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '快速删除', hant: '快速刪除' }),
module: 'speedy',
preferences: [
{
name: 'speedySelectionStyle',
label: conv({ hans: '什么时候执行标记或删除', hant: '什麼時候執行標記或刪除' }),
type: 'enum',
enumValues: { buttonClick: conv({ hans: '当我点“提交”时', hant: '當我點「提交」時' }), radioClick: conv({ hans: '当我点一个选项时', hant: '當我點一個選項時' }) }
},
// TwinkleConfig.watchSpeedyPages (array)
// Whether to add speedy tagged pages to watchlist
{
name: 'watchSpeedyPages',
label: conv({ hans: '将以下理由加入到监视列表', hant: '將以下理由加入到監視清單' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteria,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder
},
// TwinkleConfig.watchSpeedyExpiry
// If any of the above items are selected, whether to expire the watch
{
name: 'watchSpeedyExpiry',
label: conv({ hans: '当标记页面时,加入到监视列表的期限', hant: '當標記頁面時,加入到監視清單的期限' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.markSpeedyPagesAsPatrolled (boolean)
// If, when applying speedy template to page, to mark the page as patrolled (if the page was reached from NewPages)
{
name: 'markSpeedyPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
type: 'boolean'
},
// TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array)
// What types of actions should result that the author of the page being notified of nomination
{
name: 'notifyUserOnSpeedyDeletionNomination',
label: conv({ hans: '仅在使用以下理由时通知页面创建者', hant: '僅在使用以下理由時通知頁面建立者' }),
helptip: conv({ hans: '尽管您在对话框中选择通知,通知仍只会在使用这些理由时发出。', hant: '儘管您在對話方塊中選擇通知,通知仍只會在使用這些理由時發出。' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteriaNotification,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder
},
// TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings)
// On what types of speedy deletion notifications shall the user be welcomed
// with a "firstarticle" notice if his talk page has not yet been created.
{
name: 'welcomeUserOnSpeedyDeletionNotification',
label: conv({ hans: '在使用以下理由时欢迎页面创建者', hant: '在使用以下理由時歡迎頁面建立者' }),
helptip: conv({ hans: '欢迎模板仅在用户被通知时加入,使用的模板是{{firstarticle}}。', hant: '歡迎模板僅在使用者被通知時加入,使用的模板是{{firstarticle}}。' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdCriteriaNotification,
setDisplayOrder: Twinkle.config.commonSets.csdCriteriaNotificationDisplayOrder
},
// TwinkleConfig.promptForSpeedyDeletionSummary (array of strings)
{
name: 'promptForSpeedyDeletionSummary',
label: conv({ hans: '使用以下理由删除时允许编辑删除理由', hant: '使用以下理由刪除時允許編輯刪除理由' }),
adminOnly: true,
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
// TwinkleConfig.openUserTalkPageOnSpeedyDelete (array of strings)
// What types of actions that should result user talk page to be opened when speedily deleting (admin only)
{
name: 'openUserTalkPageOnSpeedyDelete',
label: conv({ hans: '使用以下理由时打开用户讨论页', hant: '使用以下理由時打開使用者討論頁' }),
adminOnly: true,
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
// TwinkleConfig.deleteTalkPageOnDelete (boolean)
// If talk page if exists should also be deleted (CSD G8) when spedying a page (admin only)
{
name: 'deleteTalkPageOnDelete',
label: conv({ hans: '默认勾选“删除讨论页”', hant: '預設勾選「刪除討論頁」' }),
adminOnly: true,
type: 'boolean'
},
{
name: 'deleteRedirectsOnDelete',
label: conv({ hans: '默认勾选“删除重定向”', hant: '預設勾選「刪除重新導向」' }),
adminOnly: true,
type: 'boolean'
},
// TwinkleConfig.deleteSysopDefaultToDelete (boolean)
// Make the CSD screen default to "delete" instead of "tag" (admin only)
{
name: 'deleteSysopDefaultToDelete',
label: conv({ hans: '默认为直接删除而不是标记', hant: '預設為直接刪除而不是標記' }),
helptip: conv({ hans: '如果已放置快速删除标记,则永远默认为删除模式。', hant: '如果已放置快速刪除標記,則永遠預設為刪除模式。' }),
adminOnly: true,
type: 'boolean'
},
// TwinkleConfig.speedyWindowWidth (integer)
// Defines the width of the Twinkle SD window in pixels
{
name: 'speedyWindowWidth',
label: conv({ hans: '快速删除对话框宽度(像素)', hant: '快速刪除對話方塊寬度(像素)' }),
type: 'integer'
},
// TwinkleConfig.speedyWindowWidth (integer)
// Defines the width of the Twinkle SD window in pixels
{
name: 'speedyWindowHeight',
label: conv({ hans: '快速删除对话框高度(像素)', hant: '快速刪除對話方塊高度(像素)' }),
helptip: conv({ hans: '如果您有一台很大的显示器,您可以将此调高。', hant: '如果您有一台很大的顯示器,您可以將此調高。' }),
type: 'integer'
},
{
name: 'logSpeedyNominations',
label: conv({ hans: '在用户空间中记录所有快速删除提名', hant: '在使用者空間中記錄所有快速刪除提名' }),
helptip: conv({ hans: '非管理员无法访问到已删除的贡献,用户空间日志提供了一个很好的方法来记录这些历史。', hant: '非管理員無法存取到已刪除的貢獻,使用者空間日誌提供了一個很好的方法來記錄這些歷史。' }),
type: 'boolean'
},
{
name: 'speedyLogPageName',
label: conv({ hans: '在此页保留日志', hant: '在此頁保留日誌' }),
helptip: conv({ hans: '在此框中输入子页面名称,您将在User:<i>用户名</i>/<i>子页面</i>找到CSD日志。仅在启用日志时工作。', hant: '在此框中輸入子頁面名稱,您將在User:<i>使用者名稱</i>/<i>子頁面</i>找到CSD日誌。僅在啟用日誌時工作。' }),
type: 'string'
},
{
name: 'noLogOnSpeedyNomination',
label: conv({ hans: '在使用以下理由时不做记录', hant: '在使用以下理由時不做記錄' }),
type: 'set',
setValues: Twinkle.config.commonSets.csdAndDICriteria,
setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
},
{
name: 'enlargeG11Input',
label: conv({ hans: '扩大CSD G11的按钮', hant: '擴大CSD G11的按鈕' }),
helptip: conv({ hans: '扩为默认的两倍大。', hant: '擴為預設的兩倍大。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '标记', hant: '標記' }),
module: 'tag',
preferences: [
{
name: 'watchTaggedPages',
label: conv({ hans: '标记时加入到监视列表', hant: '標記時加入到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'watchMergeDiscussions',
label: conv({ hans: '加入合并讨论时监视讨论页', hant: '加入合併討論時監視討論頁' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'markTaggedPagesAsMinor',
label: conv({ hans: '将标记标记为小修改', hant: '將標記標記為小修改' }),
type: 'boolean'
},
{
name: 'markTaggedPagesAsPatrolled',
label: conv({ hans: '默认勾选“标记页面为已巡查”框', hant: '預設勾選「標記頁面為已巡查」框' }),
type: 'boolean'
},
{
name: 'groupByDefault',
label: conv({ hans: '默认勾选“合并到{{multiple issues}}”复选框', hant: '預設勾選「合併到{{multiple issues}}」核取方塊' }),
type: 'boolean'
},
{
name: 'tagArticleSortOrder',
label: conv({ hans: '条目标记的默认查看方式', hant: '條目標記的預設檢視方式' }),
type: 'enum',
enumValues: { cat: conv({ hans: '按类型', hant: '按類別' }), alpha: '按字母' }
},
{
name: 'customTagList',
label: conv({ hans: '自定义条目维护标记', hant: '自訂條目維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customFileTagList',
label: conv({ hans: '自定义文件维护标记', hant: '自訂檔案維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customRedirectTagList',
label: conv({ hans: '自定义重定向维护标记', hant: '自訂重新導向維護標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: '小作品',
module: 'stub',
preferences: [
{
name: 'watchStubbedPages',
label: conv({ hans: '标记时加入到监视列表', hant: '標記時加入到監視清單' }),
type: 'boolean'
},
{
name: 'markStubbedPagesAsMinor',
label: conv({ hans: '将小作品标记为小修改', hant: '將小作品標記為小修改' }),
type: 'boolean'
},
{
name: 'markStubbedPagesAsPatrolled',
label: conv({ hans: '默认勾选“标记页面为已巡查”框', hant: '預設勾選「標記頁面為已巡查」框' }),
type: 'boolean'
},
{
name: 'stubArticleSortOrder',
label: conv({ hans: '条目小作品的默认查看方式', hant: '條目小作品的預設檢視方式' }),
type: 'enum',
enumValues: { cat: conv({ hans: '按类型', hant: '按類別' }), alpha: '按字母' }
},
{
name: 'customStubList',
label: conv({ hans: '自定义条目小作品标记', hant: '自訂條目小作品標記' }),
helptip: conv({ hans: '这些会出现在列表的末尾。', hant: '這些會出現在列表的末尾。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
}
]
},
{
title: '通告',
module: 'talkback',
preferences: [
{
name: 'markTalkbackAsMinor',
label: conv({ hans: '将通告标记为小修改', hant: '將通告標記為小修改' }),
type: 'boolean'
},
{
name: 'insertTalkbackSignature',
label: conv({ hans: '通告时加入签名', hant: '通告時加入簽名' }),
helptip: conv({ hans: 'Flow页除外。', hant: 'Flow頁除外。' }),
type: 'boolean'
},
{
name: 'talkbackHeading',
label: conv({ hans: '通告所用的小节标题', hant: '通告所用的小節標題' }),
type: 'string'
},
{
name: 'mailHeading',
label: conv({ hans: '“有新邮件”所用的小节标题', hant: '「有新郵件」所用的小節標題' }),
type: 'string'
}
]
},
{
title: conv({ hans: '取消链入', hant: '取消連入' }),
module: 'unlink',
preferences: [
// TwinkleConfig.unlinkNamespaces (array)
// In what namespaces unlink should happen, default in 0 (article) and 100 (portal)
{
name: 'unlinkNamespaces',
label: conv({ hans: '取消以下命名空间中的反向链接', hant: '取消以下命名空間中的反向連結' }),
helptip: conv({ hans: '请避免选择讨论页,因这样会导致Twinkle试图修改讨论存档。', hant: '請避免選擇討論頁,因這樣會導致Twinkle試圖修改討論存檔。' }),
type: 'set',
setValues: Twinkle.config.commonSets.namespacesNoSpecial
}
]
},
{
title: conv({ hans: '警告用户', hant: '警告使用者' }),
module: 'warn',
preferences: [
// TwinkleConfig.defaultWarningGroup (int)
// if true, watch the page which has been dispatched an warning or notice, if false, default applies
{
name: 'defaultWarningGroup',
label: conv({ hans: '默认警告级别', hant: '預設警告級別' }),
type: 'enum',
enumValues: {
1: '1:提醒',
2: '2:注意',
3: '3:警告',
4: conv({ hans: '4:最后警告', hant: '4:最後警告' }),
5: '4im:唯一警告',
6: conv({ hans: '单层级提醒', hant: '單層級提醒' }),
7: conv({ hans: '单层级警告', hant: '單層級警告' }),
// 8 was used for block templates before #260
9: conv({ hans: '自定义警告', hant: '自訂警告' }),
10: '所有警告模板',
11: conv({ hans: '自动选择层级(1-4)', hant: '自動選擇層級(1-4)' })
}
},
// TwinkleConfig.combinedSingletMenus (boolean)
// if true, show one menu with both single-issue notices and warnings instead of two separately
{
name: 'combinedSingletMenus',
label: conv({ hans: '将两个单层级菜单合并成一个', hant: '將兩個單層級選單合併成一個' }),
helptip: conv({ hans: '当启用此选项时,无论默认警告级别选择单层级通知或单层级警告皆属于此项。', hant: '當啟用此選項時,無論預設警告級別選擇單層級通知或單層級警告皆屬於此項。' }),
type: 'boolean'
},
// TwinkleConfig.showSharedIPNotice may take arguments:
// true: to show shared ip notice if an IP address
// false: to not print the notice
{
name: 'showSharedIPNotice',
label: conv({ hans: '在IP讨论页上显示附加信息', hant: '在IP討論頁上顯示附加資訊' }),
helptip: '使用的模板是{{SharedIPAdvice}}。',
type: 'boolean'
},
// TwinkleConfig.watchWarnings (string)
// Watchlist setting for the page which has been dispatched an warning or notice
{
name: 'watchWarnings',
label: conv({ hans: '警告时加入用户讨论页到监视列表', hant: '警告時加入使用者討論頁到監視清單' }),
helptip: conv({ hans: '注意:如果对方使用Flow,对应讨论串总会加到监视列表中。', hant: '注意:如果對方使用Flow,對應討論串總會加到監視清單中。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.oldSelect (boolean)
// if true, use the native select menu rather the jquery chosen-based one
{
name: 'oldSelect',
label: conv({ hans: '使用不可搜索的经典菜单', hant: '使用不可搜尋的經典選單' }),
type: 'boolean'
},
{
name: 'customWarningList',
label: conv({ hans: '自定义警告模板', hant: '自訂警告模板' }),
helptip: conv({ hans: '您可以加入模板或用户子页面。自定义警告会出现在警告对话框中“自定义警告”一节。', hant: '您可以加入模板或使用者子頁面。自訂警告會出現在警告對話方塊中「自訂警告」一節。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字(和编辑摘要)', hant: '顯示的文字(和編輯摘要)' })
}
]
},
{
title: conv({ hans: '欢迎用户', hant: '歡迎使用者' }),
module: 'welcome',
preferences: [
{
name: 'topWelcomes',
label: conv({ hans: '将欢迎放在用户讨论页的最上方', hant: '將歡迎放在使用者討論頁的最上方' }),
type: 'boolean'
},
{
name: 'watchWelcomes',
label: conv({ hans: '在欢迎时将用户讨论页加入监视列表', hant: '在歡迎時將使用者討論頁加入監視清單' }),
helptip: conv({ hans: '您将可以关注新手如何与他人协作,并能够适时地提供帮助。', hant: '您將可以關注新手如何與他人協作,並能夠適時地提供幫助。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
/*
{
name: 'insertUsername',
label: wgULS('Add your username to the template (where applicable)'),
helptip: "Some welcome templates have an opening sentence like \"Hi, I'm <username>. Welcome\" etc. If you turn off this option, these templates will not display your username in that way.",
type: 'boolean'
},
*/
{
name: 'quickWelcomeMode',
label: conv({ hans: '在差异页面单击“欢迎”链接时将会', hant: '在差異頁面點擊「歡迎」連結時將會' }),
helptip: conv({ hans: '如果您选择自动欢迎,将会使用下方指定的模板。', hant: '如果您選擇自動歡迎,將會使用下方指定的模板。' }),
type: 'enum',
enumValues: { auto: conv({ hans: '自动欢迎', hant: '自動歡迎' }), norm: conv({ hans: '要求您选择模板', hant: '要求您選擇模板' }) }
},
{
name: 'quickWelcomeTemplate',
label: conv({ hans: '自动欢迎时所使用的模板', hant: '自動歡迎時所使用的模板' }),
helptip: conv({ hans: '输入欢迎模板的名称,不包含大括号,将会加入给定的条目链接。', hant: '輸入歡迎模板的名稱,不包含大括號,將會加入給定的條目連結。' }),
type: 'string'
},
{
name: 'customWelcomeList',
label: conv({ hans: '自定义欢迎模板', hant: '自訂歡迎模板' }),
helptip: conv({ hans: '您可以加入其他欢迎模板,或是欢迎模板的用户子页面(以User:开头)。别忘了这些模板会在用户讨论页上替换引用。', hant: '您可以加入其他歡迎模板,或是歡迎模板的使用者子頁面(以User:開頭)。別忘了這些模板會在使用者討論頁上替換引用。' }),
type: 'customList',
customListValueTitle: conv({ hans: '模板名(不含大括号)', hant: '模板名(不含大括號)' }),
customListLabelTitle: conv({ hans: '显示的文字', hant: '顯示的文字' })
},
{
name: 'customWelcomeSignature',
label: conv({ hans: '在自定义模板中自动签名', hant: '在自訂模板中自動簽名' }),
helptip: conv({ hans: '如果您的自动欢迎模板包含内置签名,请关闭此项。', hant: '如果您的自動歡迎模板包含內建簽名,請關閉此項。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '存废讨论', hant: '存廢討論' }),
module: 'xfd',
preferences: [
{
name: 'logXfdNominations',
label: conv({ hans: '在用户空间中记录所有存废讨论提名', hant: '在使用者空間中記錄所有存廢討論提名' }),
helptip: conv({ hans: '该日志供您追踪所有通过Twinkle提交的存废讨论', hant: '該日誌供您追蹤所有透過Twinkle提交的存廢討論' }),
type: 'boolean'
},
{
name: 'xfdLogPageName',
label: conv({ hans: '在此页保留日志', hant: '在此頁保留日誌' }),
helptip: conv({ hans: '在此框中输入子页面名称,您将在User:<i>用户名</i>/<i>子页面</i>找到XFD日志。仅在启用日志时工作。', hant: '在此框中輸入子頁面名稱,您將在User:<i>使用者名稱</i>/<i>子頁面</i>找到XFD日誌。僅在啟用日誌時工作。' }),
type: 'string'
},
{
name: 'noLogOnXfdNomination',
label: conv({ hans: '在使用以下理由时不做记录', hant: '在使用以下理由時不做記錄' }),
type: 'set',
setValues: Twinkle.config.commonSets.xfdCriteria,
setDisplayOrder: Twinkle.config.commonSets.xfdCriteriaDisplayOrder
},
// TwinkleConfig.xfdWatchPage (string)
// The watchlist setting of the page being nominated for XfD.
{
name: 'xfdWatchPage',
label: conv({ hans: '加入提名的页面到监视列表', hant: '加入提名的頁面到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.xfdWatchDiscussion (string)
// The watchlist setting of the newly created XfD page (for those processes that create discussion pages for each nomination),
// or the list page for the other processes.
{
name: 'xfdWatchDiscussion',
label: conv({ hans: '加入存废讨论页到监视列表', hant: '加入存廢討論頁到監視清單' }),
helptip: conv({ hans: '当日的页面。', hant: '當日的頁面。' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.xfdWatchUser (string)
// The watchlist setting of the user talk page if they receive a notification.
{
name: 'xfdWatchUser',
label: conv({ hans: '加入创建者讨论页到监视列表(在通知时)', hant: '加入建立者討論頁到監視清單(在通知時)' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
{
name: 'markXfdPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
helptip: conv({ hans: '基于技术原因,页面仅会在由Special:NewPages到达时被标记为已巡查。', hant: '基於技術原因,頁面僅會在由Special:NewPages到達時被標記為已巡查。' }),
type: 'boolean'
},
{
name: 'FwdCsdToXfd',
label: conv({ hans: '提删类型增加转交自快速删除候选', hant: '提刪類別增加轉交自快速刪除候選' }),
helptip: conv({ hans: '请确保您充分了解[[Wikipedia:快速删除方针]]才开启此功能。', hant: '請確保您充分了解[[Wikipedia:快速刪除方針]]才開啟此功能。' }),
type: 'boolean'
},
{
name: 'afdDefaultCategory',
label: conv({ hans: '默认提删类型', hant: '預設提刪類別' }),
helptip: conv({ hans: '若选择“相同于上次选择”将使用localStorage来记忆。', hant: '若選擇「相同於上次選擇」將使用localStorage來記憶。' }),
type: 'enum',
enumValues: { delete: conv({ hans: '删除', hant: '刪除' }), same: conv({ hans: '相同于上次选择', hant: '相同於上次選擇' }) }
},
{
name: 'afdFameDefaultReason',
label: conv({ hans: '默认关注度提删理由', hant: '預設關注度提刪理由' }),
helptip: conv({ hans: '用于批量提删。', hant: '用於批次提刪。' }),
type: 'string'
},
{
name: 'afdSubstubDefaultReason',
label: conv({ hans: '默认小小作品提删理由', hant: '預設小小作品提刪理由' }),
helptip: conv({ hans: '用于批量提删。', hant: '用於批次提刪。' }),
type: 'string'
}
]
},
{
title: conv({ hans: '关闭存废讨论', hant: '關閉存廢討論' }),
module: 'close',
preferences: [
{
name: 'XfdClose',
label: conv({ hans: '在存废讨论显示关闭讨论按钮', hant: '在存廢討論顯示關閉討論按鈕' }),
helptip: conv({ hans: '请确保您充分了解[[Wikipedia:关闭存废讨论指引]]才开启此功能。', hant: '請確保您充分了解[[Wikipedia:關閉存廢討論指引]]才開啟此功能。' }),
type: 'enum',
enumValues: { hide: conv({ hans: '不显示', hant: '不顯示' }), nonadminonly: conv({ hans: '只包含非管理员可使用选项', hant: '只包含非管理員可使用選項' }), all: conv({ hans: '显示所有选项', hant: '顯示所有選項' }) }
}
]
},
{
title: conv({ hans: '侵犯著作权', hant: '侵犯著作權' }),
module: 'copyvio',
preferences: [
// TwinkleConfig.copyvioWatchPage (string)
// The watchlist setting of the page being nominated for XfD.
{
name: 'copyvioWatchPage',
label: conv({ hans: '加入提报的页面到监视列表', hant: '加入提報的頁面到監視清單' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.copyvioWatchUser (string)
// The watchlist setting of the user if he receives a notification.
{
name: 'copyvioWatchUser',
label: conv({ hans: '加入创建者讨论页到监视列表(在通知时)', hant: '加入建立者討論頁到監視清單(在通知時)' }),
type: 'enum',
enumValues: Twinkle.config.watchlistEnums
},
// TwinkleConfig.markCopyvioPagesAsPatrolled (boolean)
// If, when applying copyvio template to page, to mark the page as patrolled (if the page was reached from NewPages)
{
name: 'markCopyvioPagesAsPatrolled',
label: conv({ hans: '标记时标记页面为已巡查(如可能)', hant: '標記時標記頁面為已巡查(如可能)' }),
helptip: conv({ hans: '基于技术原因,页面仅会在由Special:NewPages到达时被标记为已巡查。', hant: '基於技術原因,頁面僅會在由Special:NewPages到達時被標記為已巡查。' }),
type: 'boolean'
}
]
},
{
title: conv({ hans: '隐藏', hant: '隱藏' }),
hidden: true,
preferences: [
// twinkle.js: portlet setup
{
name: 'portletArea',
type: 'string'
},
{
name: 'portletId',
type: 'string'
},
{
name: 'portletName',
type: 'string'
},
{
name: 'portletType',
type: 'string'
},
{
name: 'portletNext',
type: 'string'
},
// twinklefluff.js: defines how many revision to query maximum, maximum possible is 50, default is 50
{
name: 'revertMaxRevisions',
type: 'integer'
},
// twinklebatchdelete.js: How many pages should be processed maximum
{
name: 'batchMax',
type: 'integer',
adminOnly: true
},
// How many pages should be processed at a time by deprod and batchdelete/protect/undelete
{
name: 'batchChunks',
type: 'integer',
adminOnly: true
}
]
}
]; // end of Twinkle.config.sections
Twinkle.config.init = function twinkleconfigInit() {
// create the config page at Twinkle.getPref('configPage')
if (mw.config.get('wgPageName') === Twinkle.getPref('configPage') &&
mw.config.get('wgAction') === 'view') {
if (!document.getElementById('twinkle-config')) {
return; // maybe the page is misconfigured, or something - but any attempt to modify it will be pointless
}
// set style (the url() CSS function doesn't seem to work from wikicode - ?!)
document.getElementById('twinkle-config-titlebar').style.backgroundImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB%2FqqA%2BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhQTFRFr73ZobTPusjdsMHZp7nVwtDhzNbnwM3fu8jdq7vUt8nbxtDkw9DhpbfSvMrfssPZqLvVztbno7bRrr7W1d%2Fs1N7qydXk0NjpkW7Q%2BgAAADVJREFUeNoMwgESQCAAAMGLkEIi%2FP%2BnbnbpdB59app5Vdg0sXAoMZCpGoFbK6ciuy6FX4ABAEyoAef0BXOXAAAAAElFTkSuQmCC)';
var contentdiv = document.getElementById('twinkle-config-content');
contentdiv.textContent = ''; // clear children
// let user know about possible conflict with monobook.js/vector.js file
// (settings in that file will still work, but they will be overwritten by twinkleoptions.js settings)
var contentnotice = document.createElement('p');
// I hate innerHTML, but this is one thing it *is* good for...
contentnotice.innerHTML = '<b>' + conv({ hans: '在这里修改您的参数设置之前,', hant: '在這裡修改您的偏好設定之前,' }) + '</b>' + conv({ hans: '确认您已移除了', hant: '確認您已移除了' }) + '<a href="' + mw.util.getUrl('Special:MyPage/skin.js') + '" title="Special:MyPage/skin.js">' + conv({ hans: '用户JavaScript文件', hant: '使用者JavaScript檔案' }) + '</a>' + conv({ hans: '中任何旧的', hant: '中任何舊的' }) + '<code>FriendlyConfig</code>' + conv({ hans: '设置。', hant: '設定。' });
contentdiv.appendChild(contentnotice);
// look and see if the user does in fact have any old settings in their skin JS file
var skinjs = new Morebits.wiki.page('User:' + mw.config.get('wgUserName') + '/' + mw.config.get('skin') + '.js');
skinjs.setCallbackParameters(contentnotice);
skinjs.load(Twinkle.config.legacyPrefsNotice);
// start a table of contents
var toctable = document.createElement('div');
toctable.className = 'toc';
toctable.style.marginLeft = '0.4em';
// create TOC title
var toctitle = document.createElement('div');
toctitle.id = 'toctitle';
var toch2 = document.createElement('h2');
toch2.textContent = conv({ hans: '目录 ', hant: '目錄 ' });
toctitle.appendChild(toch2);
// add TOC show/hide link
var toctoggle = document.createElement('span');
toctoggle.className = 'toctoggle';
toctoggle.appendChild(document.createTextNode('['));
var toctogglelink = document.createElement('a');
toctogglelink.className = 'internal';
toctogglelink.setAttribute('href', '#tw-tocshowhide');
toctogglelink.textContent = conv({ hans: '隐藏', hant: '隱藏' });
toctoggle.appendChild(toctogglelink);
toctoggle.appendChild(document.createTextNode(']'));
toctitle.appendChild(toctoggle);
toctable.appendChild(toctitle);
// create item container: this is what we add stuff to
var tocul = document.createElement('ul');
toctogglelink.addEventListener('click', function twinkleconfigTocToggle() {
var $tocul = $(tocul);
$tocul.toggle();
if ($tocul.find(':visible').length) {
toctogglelink.textContent = conv({ hans: '隐藏', hant: '隱藏' });
} else {
toctogglelink.textContent = conv({ hans: '显示', hant: '顯示' });
}
}, false);
toctable.appendChild(tocul);
contentdiv.appendChild(toctable);
var contentform = document.createElement('form');
contentform.setAttribute('action', 'javascript:void(0)'); // was #tw-save - changed to void(0) to work around Chrome issue
contentform.addEventListener('submit', Twinkle.config.save, true);
contentdiv.appendChild(contentform);
var container = document.createElement('table');
container.style.width = '100%';
contentform.appendChild(container);
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // i.e. "continue" in this context
}
// add to TOC
var tocli = document.createElement('li');
tocli.className = 'toclevel-1';
var toca = document.createElement('a');
toca.setAttribute('href', '#' + section.module);
toca.appendChild(document.createTextNode(section.title));
tocli.appendChild(toca);
tocul.appendChild(tocli);
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.setAttribute('colspan', '3');
var heading = document.createElement('h4');
heading.style.borderBottom = '1px solid gray';
heading.style.marginTop = '0.2em';
heading.id = section.module;
heading.appendChild(document.createTextNode(section.title));
cell.appendChild(heading);
row.appendChild(cell);
container.appendChild(row);
var rowcount = 1; // for row banding
// add each of the preferences to the form
$(section.preferences).each(function(prefkey, pref) {
if (pref.adminOnly && !Morebits.userIsSysop) {
return true; // i.e. "continue" in this context
}
row = document.createElement('tr');
row.style.marginBottom = '0.2em';
// create odd row banding
if (rowcount++ % 2 === 0) {
row.style.backgroundColor = 'rgba(128, 128, 128, 0.1)';
}
cell = document.createElement('td');
var label, input, gotPref = Twinkle.getPref(pref.name);
switch (pref.type) {
case 'boolean': // create a checkbox
cell.setAttribute('colspan', '2');
label = document.createElement('label');
input = document.createElement('input');
input.setAttribute('type', 'checkbox');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
if (gotPref === true) {
input.setAttribute('checked', 'checked');
}
label.appendChild(input);
label.appendChild(document.createTextNode(pref.label));
cell.appendChild(label);
break;
case 'string': // create an input box
case 'integer':
// add label to first column
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add input box to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
if (pref.type === 'integer') {
input.setAttribute('size', 6);
input.setAttribute('type', 'number');
input.setAttribute('step', '1'); // integers only
}
if (gotPref) {
input.setAttribute('value', gotPref);
}
cell.appendChild(input);
break;
case 'enum': // create a combo box
// add label to first column
// note: duplicates the code above, under string/integer
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add input box to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
input = document.createElement('select');
input.setAttribute('id', pref.name);
input.setAttribute('name', pref.name);
var optionExists = false;
$.each(pref.enumValues, function(enumvalue, enumdisplay) {
var option = document.createElement('option');
option.setAttribute('value', enumvalue);
if ((gotPref === enumvalue) ||
// Hack to convert old boolean watchlist prefs
// to corresponding enums (added in v2.1)
(typeof gotPref === 'boolean' &&
((gotPref && enumvalue === 'yes') ||
(!gotPref && enumvalue === 'no')))) {
option.setAttribute('selected', 'selected');
optionExists = true;
}
option.appendChild(document.createTextNode(enumdisplay));
input.appendChild(option);
});
// Append user-defined value to options
if (!optionExists) {
var option = document.createElement('option');
option.setAttribute('value', gotPref);
option.setAttribute('selected', 'selected');
option.appendChild(document.createTextNode(gotPref));
input.appendChild(option);
}
cell.appendChild(input);
break;
case 'set': // create a set of check boxes
// add label first of all
cell.setAttribute('colspan', '2');
label = document.createElement('label'); // not really necessary to use a label element here, but we do it for consistency of styling
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
var checkdiv = document.createElement('div');
checkdiv.style.paddingLeft = '1em';
var worker = function(itemkey, itemvalue) {
var checklabel = document.createElement('label');
checklabel.style.marginRight = '0.7em';
checklabel.style.display = 'inline-block';
var check = document.createElement('input');
check.setAttribute('type', 'checkbox');
check.setAttribute('id', pref.name + '_' + itemkey);
check.setAttribute('name', pref.name + '_' + itemkey);
if (gotPref && gotPref.indexOf(itemkey) !== -1) {
check.setAttribute('checked', 'checked');
}
// cater for legacy integer array values for unlinkNamespaces (this can be removed a few years down the track...)
if (pref.name === 'unlinkNamespaces') {
if (gotPref && gotPref.indexOf(parseInt(itemkey, 10)) !== -1) {
check.setAttribute('checked', 'checked');
}
}
checklabel.appendChild(check);
checklabel.appendChild(document.createTextNode(itemvalue));
checkdiv.appendChild(checklabel);
};
if (pref.setDisplayOrder) {
// add check boxes according to the given display order
$.each(pref.setDisplayOrder, function(itemkey, item) {
worker(item, pref.setValues[item]);
});
} else {
// add check boxes according to the order it gets fed to us (probably strict alphabetical)
$.each(pref.setValues, worker);
}
cell.appendChild(checkdiv);
break;
case 'customList':
// add label to first column
cell.style.textAlign = 'right';
cell.style.paddingRight = '0.5em';
label = document.createElement('label');
label.setAttribute('for', pref.name);
label.appendChild(document.createTextNode(pref.label + ':'));
cell.appendChild(label);
row.appendChild(cell);
// add button to second column
cell = document.createElement('td');
cell.style.paddingRight = '1em';
var button = document.createElement('button');
button.setAttribute('id', pref.name);
button.setAttribute('name', pref.name);
button.setAttribute('type', 'button');
button.addEventListener('click', Twinkle.config.listDialog.display, false);
// use jQuery data on the button to store the current config value
$(button).data({
value: gotPref,
pref: pref
});
button.appendChild(document.createTextNode(conv({ hans: '编辑项目', hant: '編輯項目' })));
cell.appendChild(button);
break;
default:
alert('twinkleconfig: 未知类型的属性 ' + pref.name);
break;
}
row.appendChild(cell);
// add help tip
cell = document.createElement('td');
cell.style.fontSize = '90%';
cell.style.color = 'gray';
if (pref.helptip) {
// convert mentions of templates in the helptip to clickable links
cell.innerHTML = pref.helptip.replace(/{{(.+?)}}/g,
'{{<a href="' + mw.util.getUrl('Template:') + '$1" target="_blank">$1</a>}}')
.replace(/\[\[(.+?)]]/g,
'<a href="' + mw.util.getUrl('') + '$1" target="_blank">$1</a>');
}
// add reset link (custom lists don't need this, as their config value isn't displayed on the form)
if (pref.type !== 'customList') {
var resetlink = document.createElement('a');
resetlink.setAttribute('href', '#tw-reset');
resetlink.setAttribute('id', 'twinkle-config-reset-' + pref.name);
resetlink.addEventListener('click', Twinkle.config.resetPrefLink, false);
resetlink.style.cssFloat = 'right';
resetlink.style.margin = '0 0.6em';
resetlink.appendChild(document.createTextNode(conv({ hans: '复位', hant: '復位' })));
cell.appendChild(resetlink);
}
row.appendChild(cell);
container.appendChild(row);
return true;
});
return true;
});
var footerbox = document.createElement('div');
footerbox.setAttribute('id', 'twinkle-config-buttonpane');
footerbox.style.backgroundColor = '#BCCADF';
footerbox.style.padding = '0.5em';
var button = document.createElement('button');
button.setAttribute('id', 'twinkle-config-submit');
button.setAttribute('type', 'submit');
button.appendChild(document.createTextNode(conv({ hans: '保存修改', hant: '儲存修改' })));
footerbox.appendChild(button);
var footerspan = document.createElement('span');
footerspan.className = 'plainlinks';
footerspan.style.marginLeft = '2.4em';
footerspan.style.fontSize = '90%';
var footera = document.createElement('a');
footera.setAttribute('href', '#tw-reset-all');
footera.setAttribute('id', 'twinkle-config-resetall');
footera.addEventListener('click', Twinkle.config.resetAllPrefs, false);
footera.appendChild(document.createTextNode(conv({ hans: '恢复默认', hant: '恢復預設' })));
footerspan.appendChild(footera);
footerbox.appendChild(footerspan);
contentform.appendChild(footerbox);
// since all the section headers exist now, we can try going to the requested anchor
if (window.location.hash) {
var loc = window.location.hash;
window.location.hash = '';
window.location.hash = loc;
}
} else if (mw.config.get('wgNamespaceNumber') === mw.config.get('wgNamespaceIds').user &&
mw.config.get('wgTitle').indexOf(mw.config.get('wgUserName')) === 0 &&
mw.config.get('wgPageName').slice(-3) === '.js') {
var box = document.createElement('div');
// Styled in twinkle.css
box.setAttribute('id', 'twinkle-config-headerbox');
var link,
scriptPageName = mw.config.get('wgPageName').slice(mw.config.get('wgPageName').lastIndexOf('/') + 1,
mw.config.get('wgPageName').lastIndexOf('.js'));
if (scriptPageName === 'twinkleoptions') {
// place "why not try the preference panel" notice
box.setAttribute('class', 'config-twopt-box');
if (mw.config.get('wgArticleId') > 0) { // page exists
box.appendChild(document.createTextNode(conv({ hans: '这页包含您的Twinkle参数设置,您可使用', hant: '這頁包含您的Twinkle偏好設定,您可使用' })));
} else { // page does not exist
box.appendChild(document.createTextNode(conv({ hans: '您可配置您的Twinkle,通过使用', hant: '您可配置您的Twinkle,通過使用' })));
}
link = document.createElement('a');
link.setAttribute('href', mw.util.getUrl(Twinkle.getPref('configPage')));
link.appendChild(document.createTextNode(conv({ hans: 'Twinkle参数设置面板', hant: 'Twinkle偏好設定面板' })));
box.appendChild(link);
box.appendChild(document.createTextNode(conv({ hans: ',或直接编辑本页。', hant: ',或直接編輯本頁。' })));
$(box).insertAfter($('#contentSub'));
} else if (['monobook', 'vector', 'vector-2022', 'cologneblue', 'modern', 'timeless', 'minerva', 'common'].indexOf(scriptPageName) !== -1) {
// place "Looking for Twinkle options?" notice
box.setAttribute('class', 'config-userskin-box');
box.appendChild(document.createTextNode(conv({ hans: '如果您想配置您的Twinkle,请使用', hant: '如果您想配置您的Twinkle,請使用' })));
link = document.createElement('a');
link.setAttribute('href', mw.util.getUrl(Twinkle.getPref('configPage')));
link.appendChild(document.createTextNode(conv({ hans: 'Twinkle参数设置面板', hant: 'Twinkle偏好設定面板' })));
box.appendChild(link);
box.appendChild(document.createTextNode('。'));
$(box).insertAfter($('#contentSub'));
}
}
};
// Morebits.wiki.page callback from init code
Twinkle.config.legacyPrefsNotice = function twinkleconfigLegacyPrefsNotice(pageobj) {
var text = pageobj.getPageText();
var contentnotice = pageobj.getCallbackParameters();
if (text.indexOf('TwinkleConfig') !== -1 || text.indexOf('FriendlyConfig') !== -1) {
contentnotice.innerHTML = '<table class="plainlinks ombox ombox-content"><tr><td class="mbox-image">' +
'<img alt="" src="http://upload.wikimedia.org/wikipedia/en/3/38/Imbox_content.png" /></td>' +
'<td class="mbox-text"><p><big><b>在这里修改您的参数设置之前,</b>您必须移除在用户JavaScript文件中任何旧的Friendly设置。</big></p>' +
'<p>要这样做,您可以<a href="' + mw.config.get('wgScript') + '?title=User:' + encodeURIComponent(mw.config.get('wgUserName')) + '/' + mw.config.get('skin') + '.js&action=edit" target="_blank"><b>编辑您的个人JavaScript</b></a>。删除提到<code>FriendlyConfig</code>的代码。</p>' +
'</td></tr></table>';
} else {
$(contentnotice).remove();
}
};
// custom list-related stuff
Twinkle.config.listDialog = {};
Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow(dlgtable, value, label) {
var contenttr = document.createElement('tr');
// "remove" button
var contenttd = document.createElement('td');
var removeButton = document.createElement('button');
removeButton.setAttribute('type', 'button');
removeButton.addEventListener('click', function() {
$(contenttr).remove();
}, false);
removeButton.textContent = '移除';
contenttd.appendChild(removeButton);
contenttr.appendChild(contenttd);
// value input box
contenttd = document.createElement('td');
var input = document.createElement('input');
input.setAttribute('type', 'text');
input.className = 'twinkle-config-customlist-value';
input.style.width = '97%';
if (value) {
input.setAttribute('value', value);
}
contenttd.appendChild(input);
contenttr.appendChild(contenttd);
// label input box
contenttd = document.createElement('td');
input = document.createElement('input');
input.setAttribute('type', 'text');
input.className = 'twinkle-config-customlist-label';
input.style.width = '98%';
if (label) {
input.setAttribute('value', label);
}
contenttd.appendChild(input);
contenttr.appendChild(contenttd);
dlgtable.appendChild(contenttr);
};
Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) {
var $prefbutton = $(e.target);
var curvalue = $prefbutton.data('value');
var curpref = $prefbutton.data('pref');
var dialog = new Morebits.simpleWindow(720, 400);
dialog.setTitle(curpref.label);
dialog.setScriptName(conv({ hans: 'Twinkle参数设置', hant: 'Twinkle偏好設定' }));
var dialogcontent = document.createElement('div');
var dlgtable = document.createElement('table');
dlgtable.className = 'wikitable';
dlgtable.style.margin = '1.4em 1em';
dlgtable.style.width = '97%';
var dlgtbody = document.createElement('tbody');
// header row
var dlgtr = document.createElement('tr');
// top-left cell
var dlgth = document.createElement('th');
dlgth.style.width = '5%';
dlgtr.appendChild(dlgth);
// value column header
dlgth = document.createElement('th');
dlgth.style.width = '35%';
dlgth.textContent = curpref.customListValueTitle ? curpref.customListValueTitle : conv({ hans: '数值', hant: '數值' });
dlgtr.appendChild(dlgth);
// label column header
dlgth = document.createElement('th');
dlgth.style.width = '60%';
dlgth.textContent = curpref.customListLabelTitle ? curpref.customListLabelTitle : conv({ hans: '标签', hant: '標籤' });
dlgtr.appendChild(dlgth);
dlgtbody.appendChild(dlgtr);
// content rows
var gotRow = false;
$.each(curvalue, function(k, v) {
gotRow = true;
Twinkle.config.listDialog.addRow(dlgtbody, v.value, v.label);
});
// if there are no values present, add a blank row to start the user off
if (!gotRow) {
Twinkle.config.listDialog.addRow(dlgtbody);
}
// final "add" button
var dlgtfoot = document.createElement('tfoot');
dlgtr = document.createElement('tr');
var dlgtd = document.createElement('td');
dlgtd.setAttribute('colspan', '3');
var addButton = document.createElement('button');
addButton.style.minWidth = '8em';
addButton.setAttribute('type', 'button');
addButton.addEventListener('click', function() {
Twinkle.config.listDialog.addRow(dlgtbody);
}, false);
addButton.textContent = '添加';
dlgtd.appendChild(addButton);
dlgtr.appendChild(dlgtd);
dlgtfoot.appendChild(dlgtr);
dlgtable.appendChild(dlgtbody);
dlgtable.appendChild(dlgtfoot);
dialogcontent.appendChild(dlgtable);
// buttonpane buttons: [Save changes] [Reset] [Cancel]
var button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
Twinkle.config.listDialog.save($prefbutton, dlgtbody);
dialog.close();
}, false);
button.textContent = conv({ hans: '保存修改', hant: '儲存修改' });
dialogcontent.appendChild(button);
button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
Twinkle.config.listDialog.reset($prefbutton, dlgtbody);
}, false);
button.textContent = conv({ hans: '复位', hant: '復位' });
dialogcontent.appendChild(button);
button = document.createElement('button');
button.setAttribute('type', 'submit'); // so Morebits.simpleWindow puts the button in the button pane
button.addEventListener('click', function() {
dialog.close(); // the event parameter on this function seems to be broken
}, false);
button.textContent = '取消';
dialogcontent.appendChild(button);
dialog.setContent(dialogcontent);
dialog.display();
};
// Resets the data value, re-populates based on the new (default) value, then saves the
// old data value again (less surprising behaviour)
Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset(button, tbody) {
// reset value on button
var $button = $(button);
var curpref = $button.data('pref');
var oldvalue = $button.data('value');
Twinkle.config.resetPref(curpref);
// reset form
var $tbody = $(tbody);
$tbody.find('tr').slice(1).remove(); // all rows except the first (header) row
// add the new values
var curvalue = $button.data('value');
$.each(curvalue, function(k, v) {
Twinkle.config.listDialog.addRow(tbody, v.value, v.label);
});
// save the old value
$button.data('value', oldvalue);
};
Twinkle.config.listDialog.save = function twinkleconfigListDialogSave(button, tbody) {
var result = [];
var current = {};
$(tbody).find('input[type="text"]').each(function(inputkey, input) {
if ($(input).hasClass('twinkle-config-customlist-value')) {
current = { value: input.value };
} else {
current.label = input.value;
// exclude totally empty rows
if (current.value || current.label) {
result.push(current);
}
}
});
$(button).data('value', result);
};
// reset/restore defaults
Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) {
var wantedpref = e.target.id.substring(21); // "twinkle-config-reset-" prefix is stripped
// search tactics
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // continue: skip impossibilities
}
var foundit = false;
$(section.preferences).each(function(prefkey, pref) {
if (pref.name !== wantedpref) {
return true; // continue
}
Twinkle.config.resetPref(pref);
foundit = true;
return false; // break
});
if (foundit) {
return false; // break
}
});
return false; // stop link from scrolling page
};
Twinkle.config.resetPref = function twinkleconfigResetPref(pref) {
switch (pref.type) {
case 'boolean':
document.getElementById(pref.name).checked = Twinkle.defaultConfig[pref.name];
break;
case 'string':
case 'integer':
case 'enum':
document.getElementById(pref.name).value = Twinkle.defaultConfig[pref.name];
break;
case 'set':
$.each(pref.setValues, function(itemkey) {
if (document.getElementById(pref.name + '_' + itemkey)) {
document.getElementById(pref.name + '_' + itemkey).checked = Twinkle.defaultConfig[pref.name].indexOf(itemkey) !== -1;
}
});
break;
case 'customList':
$(document.getElementById(pref.name)).data('value', Twinkle.defaultConfig[pref.name]);
break;
default:
alert('twinkleconfig: unknown data type for preference ' + pref.name);
break;
}
};
Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() {
// no confirmation message - the user can just refresh/close the page to abort
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.hidden || (section.adminOnly && !Morebits.userIsSysop)) {
return true; // continue: skip impossibilities
}
$(section.preferences).each(function(prefkey, pref) {
if (!pref.adminOnly || Morebits.userIsSysop) {
Twinkle.config.resetPref(pref);
}
});
return true;
});
return false; // stop link from scrolling page
};
Twinkle.config.save = function twinkleconfigSave(e) {
Morebits.status.init(document.getElementById('twinkle-config-content'));
var userjs = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceIds').user] + ':' + mw.config.get('wgUserName') + '/twinkleoptions.js';
var wikipedia_page = new Morebits.wiki.page(userjs, conv({ hans: '保存参数设置到 ', hant: '儲存偏好設定到 ' }) + userjs);
wikipedia_page.setCallbackParameters(e.target);
wikipedia_page.load(Twinkle.config.writePrefs);
return false;
};
Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
var form = pageobj.getCallbackParameters();
// this is the object which gets serialized into JSON; only
// preferences that this script knows about are kept
var newConfig = {optionsVersion: 2.1};
// a comparison function is needed later on
// it is just enough for our purposes (i.e. comparing strings, numbers, booleans,
// arrays of strings, and arrays of { value, label })
// and it is not very robust: e.g. compare([2], ["2"]) === true, and
// compare({}, {}) === false, but it's good enough for our purposes here
var compare = function(a, b) {
if ($.isArray(a)) {
if (a.length !== b.length) {
return false;
}
var asort = a.sort(), bsort = b.sort();
for (var i = 0; asort[i]; ++i) {
// comparison of the two properties of custom lists
if ((typeof asort[i] === 'object') && (asort[i].label !== bsort[i].label ||
asort[i].value !== bsort[i].value)) {
return false;
} else if (asort[i].toString() !== bsort[i].toString()) {
return false;
}
}
return true;
}
return a === b;
};
$(Twinkle.config.sections).each(function(sectionkey, section) {
if (section.adminOnly && !Morebits.userIsSysop) {
return; // i.e. "continue" in this context
}
// reach each of the preferences from the form
$(section.preferences).each(function(prefkey, pref) {
var userValue; // = undefined
// only read form values for those prefs that have them
if (!pref.adminOnly || Morebits.userIsSysop) {
if (!section.hidden) {
switch (pref.type) {
case 'boolean': // read from the checkbox
userValue = form[pref.name].checked;
break;
case 'string': // read from the input box or combo box
case 'enum':
userValue = form[pref.name].value;
break;
case 'integer': // read from the input box
userValue = parseInt(form[pref.name].value, 10);
if (isNaN(userValue)) {
Morebits.status.warn(conv({ hans: '保存', hant: '儲存' }), conv({ hans: '您为 ', hant: '您為 ' }) + pref.name + ' 指定的值(' + pref.value + conv({ hans: ')不合法,会继续保存操作,但此值将会跳过。', hant: ')不合法,會繼續儲存操作,但此值將會跳過。' }));
userValue = null;
}
break;
case 'set': // read from the set of check boxes
userValue = [];
if (pref.setDisplayOrder) {
// read only those keys specified in the display order
$.each(pref.setDisplayOrder, function(itemkey, item) {
if (form[pref.name + '_' + item].checked) {
userValue.push(item);
}
});
} else {
// read all the keys in the list of values
$.each(pref.setValues, function(itemkey) {
if (form[pref.name + '_' + itemkey].checked) {
userValue.push(itemkey);
}
});
}
break;
case 'customList': // read from the jQuery data stored on the button object
userValue = $(form[pref.name]).data('value');
break;
default:
alert('twinkleconfig: 未知数据类型,属性 ' + pref.name);
break;
}
} else if (Twinkle.prefs) {
// Retain the hidden preferences that may have customised by the user from twinkleoptions.js
// undefined if not set
userValue = Twinkle.prefs[pref.name];
}
}
// only save those preferences that are *different* from the default
if (userValue !== undefined && !compare(userValue, Twinkle.defaultConfig[pref.name])) {
newConfig[pref.name] = userValue;
}
});
});
var text =
'// <nowiki>\n' +
conv({
hans:
'// twinkleoptions.js:用户Twinkle参数设置文件\n' +
'//\n' +
'// 注:修改您的参数设置最简单的办法是使用\n' +
'// Twinkle参数设置面板,在[[' + Morebits.pageNameNorm + ']]。\n' +
'//\n' +
'// 这个文件是自动生成的,您所做的任何修改(除了\n' +
'// 以一种合法的JavaScript的方式来修改这些属性值)会\n' +
'// 在下一次您点击“保存”时被覆盖。\n' +
'// 修改此文件时,请记得使用合法的JavaScript。\n' +
'\n' +
'window.Twinkle.prefs = ',
hant:
'// twinkleoptions.js:使用者Twinkle參數設定檔案\n' +
'//\n' +
'// 註:修改您的參數設定最簡單的辦法是使用\n' +
'// Twinkle參數設定面板,在[[' + Morebits.pageNameNorm + ']]。\n' +
'//\n' +
'// 這個檔案是自動產生的,您所做的任何修改(除了\n' +
'// 以一種合法的JavaScript的方式來修改這些屬性值)會\n' +
'// 在下一次您點擊「儲存」時被覆蓋。\n' +
'// 修改此檔案時,請記得使用合法的JavaScript。\n' +
'\n' +
'window.Twinkle.prefs = '
});
text += JSON.stringify(newConfig, null, 2);
text +=
';\n' +
'\n' +
conv({ hans: '// twinkleoptions.js到此为止\n', hant: '// twinkleoptions.js到此為止\n' }) +
'// </nowiki>';
pageobj.setPageText(text);
pageobj.setEditSummary(conv({ hans: '保存Twinkle参数设置:来自[[', hant: '儲存Twinkle偏好設定:來自[[' }) + Morebits.pageNameNorm + conv({ hans: ']]的自动编辑', hant: ']]的自動編輯' }));
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setCreateOption('recreate');
pageobj.save(Twinkle.config.saveSuccess);
};
Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) {
pageobj.getStatusElement().info('成功');
var noticebox = document.createElement('div');
noticebox.className = 'mw-message-box mw-message-box-success';
noticebox.style.fontSize = '100%';
noticebox.style.marginTop = '2em';
noticebox.innerHTML = '<p><b>' + conv({ hans: '您的Twinkle参数设置已被保存。', hant: '您的Twinkle偏好設定已被儲存。' }) + '</b></p><p>' + conv({ hans: '要看到这些更改,您可能需要', hant: '要看到這些更改,您可能需要' }) + '<a href="' + mw.util.getUrl('WP:BYPASS') + '" title="WP:BYPASS"><b>' + conv({ hans: '绕过浏览器缓存', hant: '繞過瀏覽器快取' }) + '</b></a>。</p>';
Morebits.status.root.appendChild(noticebox);
var noticeclear = document.createElement('br');
noticeclear.style.clear = 'both';
Morebits.status.root.appendChild(noticeclear);
};
Twinkle.addInitCallback(Twinkle.config.init);
})(jQuery);
// </nowiki>
2ce62973ad5602d737de174df6929636411cbcff
MediaWiki:Gadget-Twinkle.css
8
170
343
342
2024-08-03T04:07:33Z
黑茶
2
导入1个版本
css
text/css
/**
* Explicitly set width of TW menu so that we can use a hidden peer gadget
* to add space where the TW menu would go before it loads. See
* twinkle-pagestyles.css
*/
.skin-vector .vector-menu-dropdown #p-twinkle {
width: 3.24em;
}
/**
* In skin vector-2022, open the TW menu when mouse hovers over it. Credit to
* [[en:User:Nardog]] for this fix.
*/
#p-twinkle:hover > .vector-menu-content {
opacity: 1;
visibility: visible;
height: auto;
}
/* twinkleclose.js */
a.twinkle-close-button {
color: red;
font-weight: bold;
}
a.twinkle-close-button-disabled {
color: gray;
}
/* The additional box on user skin.js and twinklepreferences.js pages */
#twinkle-config-headerbox {
border: 1px #f60 solid;
background: #fed;
padding: 0.6em;
margin: 0.5em auto;
text-align: center;
}
/* twinkleoptions.js */
#twinkle-config-headerbox.config-twopt-box {
font-weight: bold;
width: 80%;
border-width: 2px;
}
/* skin-specific js */
#twinkle-config-headerbox.config-userskin-box {
width: 60%;
}
/* TWPREFS */
#twinkle-config-content input[type=checkbox] {
margin-right: 2px;
}
eff02fd157ce62bce708f8ddc24076a98756d7d2
MediaWiki:Gadgets-definition
8
145
344
298
2024-08-03T04:08:38Z
黑茶
2
wikitext
text/x-wiki
* J-Tool[ResourceLoader]|Jtool.js
* Twinkle[ResourceLoader|dependencies=ext.gadget.HanAssist,ext.gadget.morebits,ext.gadget.select2,mediawiki.api,mediawiki.language|rights=autoconfirmed|peers=Twinkle-pagestyles|requiresES6]|Twinkle.js|Twinkle.css|twinklearv.js|twinklewarn.js|twinkleblock.js|friendlywelcome.js|friendlytalkback.js|twinklespeedy.js|twinklecopyvio.js|twinklexfd.js|twinkleimage.js|twinkleprotect.js|friendlytag.js|twinklestub.js|twinklediff.js|twinkleunlink.js|twinklefluff.js|twinklebatchdelete.js|twinklebatchundelete.js|twinkleclose.js|twinkleconfig.js
20a58f85c7c13b609118a14eb949b70f8dde43c4
那艺娜
0
171
345
2024-08-04T12:02:27Z
黑茶
2
创建页面,内容为“'''那艺娜'''(1967年7月11日—<ref>[https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4]QQ音乐</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通…”
wikitext
text/x-wiki
'''那艺娜'''(1967年7月11日—<ref>[https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4]QQ音乐</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>[https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta]</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
a31bf010bdd6c9c03b4d6c1ffb8bc547d9891f4c
Template:Reflist
10
172
347
346
2024-08-04T12:21:47Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="reflist <!--
-->{{#if: {{{1|}}}
| columns {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }}
| references-column-width
| references-column-count references-column-count-{{#if:1|{{{1}}}}} }}
| {{#if: {{{colwidth|}}}
| references-column-width }} }}" style="<!--
-->{{#if: {{{1|}}}
| {{#iferror: {{#ifexpr: {{{1|1}}} > 1 }}
| {{column-width|{{#if:1|{{{1}}}}}}}
| {{column-count|{{#if:1|{{{1}}}}}}} }}
| {{#if: {{{colwidth|}}}
| {{column-width|{{{colwidth}}}}} }} }} list-style-type: <!--
-->{{{liststyle|{{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = decimal}}}}};">
{{{list|{{#tag:references|{{{refs|}}}|group={{{group|}}}}}}}}</div><noinclude>
{{Documentation}}
</noinclude>
4795d8947cf53545753ca196611b842301a04324
Template:Cite web
10
173
349
348
2024-08-04T12:21:48Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude><includeonly>{{#invoke:citation/CS1|citation
|CitationClass=web
}}</includeonly><noinclude>
{{documentation}}
</noinclude>
3b7682ef53d882ae11de29b97be5a15ef317eee3
Module:Category handler/blacklist
828
67
351
243
2024-08-04T12:21:52Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module contains the blacklist used by [[Module:Category handler]].
-- Pages that match Lua patterns in this list will not be categorised unless
-- categorisation is explicitly requested.
return {
'^Main Page$', -- don't categorise the main page.
-- Don't categorise the following pages or their subpages.
-- "%f[/\0]" matches if the next character is "/" or the end of the string.
'^那艺娜维基:Cascade%-protected items%f[/\0]',
'^User:UBX%f[/\0]', -- The userbox "template" space.
'^User talk:UBX%f[/\0]',
-- Don't categorise subpages of these pages, but allow
-- categorisation of the base page.
'^那艺娜维基:Template messages/.*$',
'/[aA]rchive' -- Don't categorise archives.
}
939eea9afe7dd0de8be68d71a9cbccfca2c3d6ee
Template:ISO 639 name en
10
174
353
352
2024-08-04T12:21:53Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
英語<noinclude>
{{ISO 639 name conversion template doc|{{ {{PAGENAME}} }}|en}}
</noinclude>
873f783ebcee476b68129cda93a2d1e4ba60239c
Module:CGroup/core
828
128
355
253
2024-08-04T12:21:55Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.Item(o, r)
-- See [[那艺娜维基:字詞轉換處理/公共轉換組]]
-- o: 原文。若無此屬性,應使用nil而非空字串('')。
-- r: 用於全文轉換的規則,必填。
return { type = 'item', original = o, rule = r };
end
return p
97c445f7e3f780f771b528f0f42a6367ba48b2de
Module:Citation/CS1
828
175
357
356
2024-08-04T12:21:55Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< I M P O R T E D _ F U N C T I O N S _ A N D _ V A R I B L E S >-----------------
]]
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist
local dates, year_date_check; -- functions in Module:Citation/CS1/Date_validation
local add_maint_cat, append_error, make_error_tail, reset_error, set_error, select_one, throw_error;
-- error-related functions in Module:Citation/CS1/Error
local first_set, hyphen_to_dash, is_set, in_array, substitute; -- simple functions in Module:Citation/CS1/Utilities
local has_invisible_chars, kern_quotes, pend_separator, safe_join, wrap_style, wrap_msg;
-- style-related functions in Module:Citation/CS1/Utilities
local check_for_external_link, make_external_link, make_internal_link; -- link-related functions in Module:Citation/CS1/Links
local extract_ids, build_id_list, is_embargoed, extract_id_access_levels; -- functions in Module:Citation/CS1/Identifiers
local get_people, format_people; -- functions in Module:Citation/CS1/People
local COinS; -- functions in Module:Citation/CS1/COinS
local script_concatenate, language_parameter; -- functions in Module:Citation/CS1/Language
local function load_modules (module_path, module_suffix)
cfg = mw.loadData (module_path .. 'Configuration' .. module_suffix);
whitelist = mw.loadData (module_path .. 'Whitelist' .. module_suffix);
local validation = require (module_path .. 'Date_validation' .. module_suffix);
local identifiers = require (module_path .. 'Identifiers' .. module_suffix);
local utilities = require (module_path .. 'Utilities' .. module_suffix);
local people = require (module_path .. 'People' .. module_suffix);
local links = require (module_path .. 'Links' .. module_suffix);
local errors = require (module_path .. 'Error' .. module_suffix);
local coins = require (module_path .. 'COinS' .. module_suffix);
local languages = require (module_path .. 'Language' .. module_suffix);
utilities.set_selected_modules (cfg);
links.set_selected_modules (utilities, errors);
errors.set_selected_modules (cfg, utilities, links);
identifiers.set_selected_modules (cfg, utilities, errors, links, validation);
people.set_selected_modules (cfg, utilities, errors, links);
coins.set_selected_modules (cfg, utilities, links);
languages.set_selected_modules (utilities, errors);
dates = validation.dates; -- imported functions
year_date_check = validation.year_date_check;
first_set = utilities.first_set;
hyphen_to_dash = utilities.hyphen_to_dash;
is_set = utilities.is_set;
in_array = utilities.in_array;
substitute = utilities.substitute;
has_invisible_chars = utilities.has_invisible_chars;
kern_quotes = utilities.kern_quotes;
pend_separator = utilities.pend_separator;
safe_join = utilities.safe_join;
wrap_style = utilities.wrap_style;
wrap_msg = utilities.wrap_msg;
make_external_link = links.make_external_link;
make_internal_link = links.make_internal_link;
check_for_external_link = links.check_for_external_link;
add_maint_cat = errors.add_maint_cat;
append_error = errors.append_error;
make_error_tail = errors.make_error_tail;
reset_error = errors.reset_error;
set_error = errors.set_error;
select_one = errors.select_one;
throw_error = errors.throw_error;
extract_ids = identifiers.extract_ids;
build_id_list = identifiers.build_id_list;
is_embargoed = identifiers.is_embargoed;
extract_id_access_levels = identifiers.extract_id_access_levels;
get_people = people.get_people;
format_people = people.format_people;
COinS = coins.COinS;
script_concatenate = languages.script_concatenate;
language_parameter = languages.language_parameter;
end
--[[--------------------------< D E P R E C A T E D _ P A R A M E T E R >--------------------------------------
Categorize and emit an error message when the citation contains one or more deprecated parameters. The function includes the
offending parameter name to the error message.
]]
local function deprecated_parameter (name)
append_error ('deprecated_params', {name});
end
--[[--------------------------< D I S C A R D _ P A R A M E T E R >--------------------------------------------
]]
local function discard_parameter (name, label, new_value)
if is_set (name) then
append_error ('parameter_discarded', label);
end
return new_value;
end
--[[--------------------------< S A N I T I Z E D _ P A R A M E T E R _ V A L U E >------------------------
This function is used to validate a parameter's assigned value for those parameters that have only a limited number
of allowable values (e.g. yes, y, true, no, etc). If the parameter value is empty or is in the list of allowed values,
the function returns the value; else, it emits an error message and returns the default value.
]]
local function sanitized_parameter_value (value, name, key, default)
if not is_set (value) then
return value; -- an empty parameter is ok
elseif in_array (value:lower(), cfg.keywords[key]) then
return value;
else
append_error ('invalid_param_val', {name, value}); -- not an allowed value so add error message
return default;
end
end
--[[--------------------------< E X T R A _ T E X T _ I N _ P A R A M E T E R _ C H E C K >------------------------------
]]
local function extra_text_in_parameter_check (value, type)
local good_patterns = cfg.extra_text_pattern[type]['good'];
local bad_patterns = cfg.extra_text_pattern[type]['bad'];
for _, pattern in pairs (good_patterns) do
if value:match (pattern) then
return;
end
end
for _, pattern in pairs (bad_patterns) do
if value:match (pattern) then
add_maint_cat ('extra_text', type);
return;
end
end
end
--[[--------------------------< V A L I D A T E _ D A T E >-------------------------------------------------------
Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where
we get the date used in the metadata.
Date validation supporting code is in Module:Citation/CS1/Date_validation
]]
local function validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, origin)
local error_message = '';
-- AirDate has been promoted to Date so not necessary to check it
anchor_year, error_message = dates ({['access-date']=AccessDate, ['archive-date']=ArchiveDate, ['date']=Date, ['doi-broken-date']=DoiBroken,
['embargo']=Embargo, ['lay-date']=LayDate, ['publication-date']=PublicationDate, ['year']=Year}, COinS_date);
if is_set (Year) then
if is_set (Date) then -- both |date= and |year= not normally needed;
local mismatch = year_date_check (Year, Date)
if 0 == mismatch then -- |year= does not match a year-value in |date=
append_error ('date_year_mismatch', {origin});
elseif 1 == mismatch then -- |year= matches year-value in |date=
add_maint_cat ('date_year');
end
end
anchor_year = Year; -- Year first for legacy citations and for YMD dates that require disambiguation
end
if is_set (error_message) then
append_error ('bad_date', {error_message}); -- add this error message
end
return anchor_year;
end
--[[--------------------------< D I S C A R D _ C H A P T E R >-------------------------------------------------------
仅为保持兼容性而设置。理论上可以直接调用discard_parameter()丢弃相关参数。
]]
local function discard_chapter (args)
local chap_param;
if is_set (args['Chapter']) then -- get a parameter name from one of these chapter related meta-parameters
chap_param = args:ORIGIN ('Chapter');
elseif is_set (args['TransChapter']) then
chap_param = args:ORIGIN ('TransChapter');
elseif is_set (args['ChapterURL']) then
chap_param = args:ORIGIN ('ChapterURL');
elseif is_set (args['ScriptChapter']) then
chap_param = args:ORIGIN ('ScriptChapter')
elseif is_set (args['ChapterFormat']) then
chap_param = args:ORIGIN ('ChapterFormat')
elseif is_set (args['ChapterUrlAccess']) then
chap_param = args:ORIGIN ('ChapterUrlAccess')
end
if is_set (chap_param) then -- if we found one
append_error ('chapter_ignored', {chap_param}); -- add error message
end
end
--[[--------------------------< C R E A T E _ U R L _ O B J E C T >------------------------------------------
]]
local function create_url_object (url, source, fmt, fmt_source, access, access_source)
return {
['url'] = is_set (url) and url or '',
['origin'] = is_set (source) and source or '',
['access'] = is_set (access) and sanitized_parameter_value (access, access_source, 'url-access', '') or '',
['access-origin'] = is_set (access_source) and access_source or '',
['format'] = is_set (fmt) and fmt or '',
['format-origin'] = is_set (fmt_source) and fmt_source or '',
['access-text'] = ''
}
end
--[[--------------------------< S E T _ T I T L E T Y P E >----------------------------------------------------
This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults.
Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none).
]]
local function set_titletype (cite_class, title_type)
if is_set (title_type) then
if 'none' == title_type then
title_type = ''; -- if |type=none then type parameter not displayed
end
return title_type; -- if |type= has been set to any other value use that value
end
return cfg.title_types[cite_class] or ''; -- set template's default title type; else empty string for concatenation
end
--[[--------------------------< S E T _ N O _ T R A C K I N G _ C A T S >-----------------------------------------
check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories
]]
local function set_no_tracking_cats (no_tracking, no_tracking_source, this_page)
local no_tracking_cats = sanitized_parameter_value (no_tracking, no_tracking_source, 'yes_true_y', nil);
if not is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page
if in_array (this_page.nsText, cfg.uncategorized_namespaces) then
return true; -- set no_tracking_cats
end
for _,v in ipairs (cfg.uncategorized_subpages) do -- cycle through page name patterns
if this_page.text:match (v) then -- test page name against each pattern
return true; -- set no_tracking_cats; bail out if one is found
end
end
return false;
else
return true;
end
end
--[[--------------------------< S E T _ C S 1 _ S T Y L E >----------------------------------------------------
Set style settings for CS1 citation templates. Returns separator and postscript settings
]]
local function set_cs1_style (ps)
if not is_set (ps) then -- unless explicitely set to something
ps = '.'; -- terminate the rendered citation with a period
end
return '.', ps; -- separator is a full stop
end
--[[--------------------------< S E T _ C S 2 _ S T Y L E >----------------------------------------------------
Set style settings for CS2 citation templates. Returns separator, postscript, ref settings
]]
local function set_cs2_style (ps, ref)
if not is_set (ps) then -- if |postscript= has not been set, set cs2 default
ps = ''; -- make sure it isn't nil
end
if not is_set (ref) then -- if |ref= is not set
ref = 'harv'; -- set default |ref=harv
end
return ',', ps, ref; -- separator is a comma
end
--[[--------------------------< G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S >----------------------
When |mode= is not set or when its value is invalid, use config.CitationClass and parameter values to establish
rendered style.
]]
local function get_settings_from_cite_class (ps, ref, cite_class)
local sep;
if (cite_class == 'citation') then -- for citation templates (CS2)
sep, ps, ref = set_cs2_style (ps, ref);
else -- not a citation template so CS1
sep, ps = set_cs1_style (ps);
end
return sep, ps, ref -- return them all
end
--[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------
Establish basic style settings to be used when rendering the citation. Uses |mode= if set and valid or uses
config.CitationClass from the template's #invoke: to establish style.
]]
local function set_style (mode, mode_source, ps, ref, quote, cite_class)
local sep;
mode = sanitized_parameter_value (mode, mode_source, 'mode', ''):lower();
if 'cs2' == mode then -- if this template is to be rendered in CS2 (citation) style
sep, ps, ref = set_cs2_style (ps, ref);
elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style
sep, ps = set_cs1_style (ps);
else -- anything but cs1 or cs2
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass
end
if 'none' == ps:lower() or is_set (quote) then -- if assigned value is 'none' then set it to empty string
ps = ''; -- also cs1|2 does not supply terminal punctuation when |quote= is set
end
return sep, ps, ref
end
--[[--------------------------< S W A P _ U R L S >--------------------------------------------------------------
]]
local function swap_urls (url_object, chapter_url_object, archive_url_object, dead_url)
local original_url_object = create_url_object ();
local is_dead = in_array (dead_url, cfg.keywords['deadurl-live']); -- used later when assembling archived text
if is_set (archive_url_object['url']) then
if is_set (url_object['url']) then
original_url_object = url_object;
if not is_dead then
url_object = archive_url_object;
end
elseif is_set (chapter_url_object['url']) then -- URL not set so if chapter-url is set apply archive url to it
original_url_object = chapter_url_object;
if not is_dead then
chapter_url_object = archive_url_object;
end
end
end
return original_url_object, url_object, chapter_url_object;
end
--[[--------------------------< F O R M A T _ U R L _ A C C E S S _ T E X T >---------------------------------------
从x-url-access系列参数生成相应的图标;兼容既有registration, subscription参数,优先级x-url-access > subscription > registration。
]]
local function format_url_access_text (url_object, subscription_required, registration_required)
local access_text = '';
local redundant = false;
local access = url_object['access'];
local reg = false;
local sub = false;
if is_set (access) then
if (access == 'limited') then
access_text = cfg.presentation['limited']; -- 有限度免费访问
elseif (access == 'registration') then
access_text = cfg.presentation['registration']; -- 需要免费注册
reg = true;
elseif (access == 'subscription') then
access_text = cfg.presentation['subscription']; -- 需要付费订阅
sub = true;
else
access_text = '';
end
if is_set (subscription_required) or is_set (registration_required) then
redundant = true;
end
else
if is_set (subscription_required) then
access_text = cfg.presentation['subscription']; -- 需要免费注册
sub = true;
if is_set (registration_required) then
redundant = true;
end
elseif is_set (registration_required) then
access_text = cfg.presentation['registration']; -- 需要付费订阅
reg = true
else
access_text = '';
end
end
if is_set (url_object ['url']) then
url_object['access-text'] = access_text;
if sub then
add_maint_cat ('subscription');
elseif reg then
add_maint_cat ('registration');
end
else
-- 预留报错
end
return redundant;
end
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >----------------------------------------
returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume
or formatted issue, or an empty string if neither are set.
]]
local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower)
if not is_set (volume) and not is_set (issue) then
return '';
end
if 'magazine' == cite_class or (cite_class =='map' and 'magazine' == origin) then
if is_set (volume) and is_set (issue) then
return wrap_msg ('vol-no', {sepc, volume, issue}, lower);
elseif is_set (volume) then
return wrap_msg ('vol', {sepc, volume}, lower);
else
return wrap_msg ('issue', {sepc, issue}, lower);
end
end
local vol = '';
if is_set (volume) then
if (6 < mw.ustring.len (volume)) then
vol = wrap_msg ('j-vol', {sepc, volume}, lower);
else
vol = wrap_style ('vol-bold', hyphen_to_dash (volume));
end
end
if is_set (issue) then
return vol .. wrap_msg ('j-issue', issue, lower);
end
return vol;
end
--[[-------------------------< F O R M A T _ I N S O U R C E _ L O C A T I O N >----------------------------------
Build insource_location meta-parameter from |page(s)= , |sheet(s)= , |at= and other relevant parameters.
]]
local function format_insource_location (page, pages, sheet, sheets, at, minutes, time, time_caption, section, sections, inset, cite_class, origin, sepc, nopp, lower)
local text = '';
if is_set (sheet) then
if 'journal' == origin then
text = wrap_msg ('j-sheet', sheet, lower);
else
text = wrap_msg ('sheet', {sepc, sheet}, lower);
end
elseif is_set (sheets) then
if 'journal' == origin then
text = wrap_msg ('j-sheets', sheets, lower);
else
text = wrap_msg ('sheets', {sepc, sheets}, lower);
end
end
local is_journal = 'journal' == cite_class or (cite_class == 'map' and 'journal' == origin);
if is_set (page) then
if is_journal then
text = wrap_msg ('j-page(s)', page, lower);
elseif not is_set (nopp) then
text = wrap_msg ('p-prefix', {sepc, page}, lower);
else
text = wrap_msg ('nopp', {sepc, page}, lower);
end
elseif is_set (pages) then
if is_journal then
text = wrap_msg ('j-page(s)', pages, lower);
elseif tonumber (pages) ~= nil and not is_set (nopp) then -- if pages is only digits, assume a single page number
text = wrap_msg ('p-prefix', {sepc, pages}, lower);
elseif not is_set (nopp) then
text = wrap_msg ('pp-prefix', {sepc, pages}, lower);
else
text = wrap_msg ('nopp', {sepc, pages}, lower);
end
end
if is_set (minutes) then
text = pend_separator (wrap_msg ('minutes', minutes, lower), sepc, true) .. text;
else
if is_set (time) then
if not is_set (time_caption) then
text = pend_separator (wrap_msg ('event', time, lower), sepc, true) .. text;
else
text = pend_separator (time_caption .. ' ' .. time .. text, sepc, true);
end
end
end
text = text .. pend_separator (at, sepc, true);
text = text .. pend_separator (wrap_msg ('inset', inset, lower), sepc, true);
if is_set (sections) then
text = text .. pend_separator (wrap_msg ('sections', sections, lower), sepc, true);
elseif is_set (section) then
text = text .. pend_separator (wrap_msg ('section', section, lower), sepc, true);
end
return text;
end
--[[-------------------------< F O R M A T _ P U B L I S H E R >------------------------------------------
]]
local function format_publisher (publisher_name, publication_place, periodical, cite_class, sepc)
local publisher = '';
if is_set (publisher_name) then
if is_set (publication_place) then
publisher = publication_place .. ': ' .. publisher_name;
else
publisher = publisher_name;
end
elseif is_set (publication_place) then
publisher = publication_place;
end
if is_set (publisher) then
if is_set (periodical) and
not in_array (cite_class, {'encyclopaedia', 'web', 'pressrelease', 'podcast'}) then
publisher = ' (' .. publisher .. ')';
else
publisher = pend_separator (publisher, sepc, true);
end
end
return publisher;
end
--[[-------------------------< F O R M A T _ L I N K >-------------------------------------------------
Format an external link that may or may not be raw.
]]
local function format_external_link (text, url_object, sepc)
if is_set (text) then
if is_set (url_object['url']) then
text = make_external_link (url_object['url'], text, url_object['origin']);
end
text = pend_separator (text .. url_object['format'], sepc, true);
elseif is_set (url_object['url']) then
text = make_external_link (url_object['url'], nil, url_object['origin']);
end
return text;
end
--[[-------------------------< F O R M A T _ C O N F E R E N C E >----------------------------------------
]]
local function format_conference (conference, conference_url_object, periodical, cite_class, sepc)
local conf_text = format_external_link (conference, conference_url_object, sepc);
if 'speech' == cite_class and is_set (periodical) then
-- if cite speech, periodical (perhaps because of an included |website= or |journal= parameter) is set;
conf_text = pend_separator (conf_text, sepc, false); -- then add appropriate punctuation to the end of the conference variable if set.
end
return conf_text;
end
--[[--------------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------------------------------
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single Chapter meta-
parameter (chapter_url_source used for error messages).
]]
local function format_chapter_title (scriptchapter, chapter, transchapter, chapter_url_object, no_quotes, cite_class, title_type, sepc)
local chapter_error = '';
if not is_set (chapter) then
chapter = ''; -- to be safe for concatenation
else
if false == no_quotes then
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks
chapter = wrap_style ('quoted-title', chapter);
end
end
chapter = script_concatenate (chapter, scriptchapter) -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
if is_set (transchapter) then
transchapter = wrap_style ('trans-quoted-title', transchapter);
if is_set (chapter) then
chapter = chapter .. ' ' .. transchapter;
else -- here when transchapter without chapter or script-chapter
chapter = transchapter;
chapter_error = ' ' .. set_error ('trans_missing_title', {'chapter'});
end
end
if is_set (chapter_url_object['url']) then
chapter = make_external_link (chapter_url_object['url'], chapter, chapter_url_object['origin']) .. chapter_url_object['access-text'];
-- adds bare_url_missing_title error if appropriate
end
chapter = chapter .. chapter_error;
if is_set (chapter) then
if 'map' == cite_class and is_set (title_type) then
chapter = chapter .. ' ' .. title_type;
end
chapter = pend_separator (chapter .. chapter_url_object['format'], sepc, false);
else -- |chapter= not set but |chapter-format= is so ...
chapter = pend_separator (chapter_url_object['format'], sepc, false); -- ... ChapterFormat has error message, we want to see it
end
return chapter;
end
--[[--------------------------< F O R M A T _ M A I N _ T I T L E >------------------------------------------
Format the five title parameters: |script-title=, |title=, |trans-title=, |title-link=, and |url= into a single Title meta-
parameter (url_origin and title_link_origin used for error messages).
]]
local function format_main_title (title, title_link, title_link_origin, script_title, trans_title, url_object, no_chapter_format, cite_class, periodical)
if is_set (title_link) and is_set (title) then
title = make_internal_link (title_link, title, title_link_origin);
end
if no_chapter_format or
('map' == cite_class and is_set (periodical)) then -- special case for cite map when the map is in a periodical treat as an article
title = kern_quotes (title); -- if necessary, separate title's leading and trailing quote marks from Module provided quote marks
title = wrap_style ('quoted-title', title);
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title= wrap_style ('trans-quoted-title', trans_title );
elseif 'report' == cite_class then -- no styling for cite report
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title= wrap_style ('trans-quoted-title', trans_title ); -- for cite report, use this form for trans-title
else
title = wrap_style ('italic-title', title);
title = script_concatenate (title, script_title); -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
trans_title = wrap_style ('trans-italic-title', trans_title);
end
local trans_error = '';
if is_set (trans_title) then
if is_set (title) then
trans_title = ' ' .. trans_title;
else
trans_error = ' ' .. set_error ('trans_missing_title', {'title'});
end
end
title = title .. trans_title;
if is_set (title) then
if not is_set (title_link) and is_set (url_object['url']) then
title = make_external_link (url_object['url'], title, url_object['origin']) .. url_object['access-text'] .. trans_error .. url_object['format'];
url_object = create_url_object ();
else
title = title .. trans_error;
end
end
return title, url_object;
end
--[[--------------------------< F O R M A T _ F O R M A T >--------------------------------------------------------
Applies css style to |format=, |chapter-format=, etc. Also emits an error message if the format parameter does
not have a matching url parameter. If the format parameter is not set and the url contains a file extension that
is recognized as a pdf document by MediaWiki's commons.css, this code will set the format parameter to (PDF) with
the appropriate styling.
]]
local function format_format (args)
for _, url_object in pairs (args) do
if is_set (url_object['format']) then
url_object['format'] = wrap_style ('format', url_object['format']); -- add leading space, parenthases, resize
if not is_set (url_object['url']) then
url_object['format'] = url_object['format'] .. set_error ('format_missing_url', {url_object['format-origin'], url_object['origin']});
-- add an error message
end
elseif is_set (url_object['url']) then
if url_object['url']:match ('%.pdf[%?#]?') or url_object['url']:match ('%.PDF[%?#]?') then
-- format is not set so if url is a pdf file then
url_object['format'] = wrap_style ('format', 'PDF'); -- set format to pdf
end
end
end
end
--[[--------------------------< F O R M A T _ A C C E S S D A T E >----------------------------------------------
]]
local function format_accessdate (accessdate, sepc, lower)
if is_set (accessdate) then -- first, wrap in nowrap span if date in appropriate format
if accessdate:match ('^%d%d%d%d%-%d%d%-%d%d$') then
accessdate = wrap_style ('nowrap1', accessdate); -- when accessdate is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.
elseif accessdate:match('^%a+%s*%d%d?,%s+%d%d%d%d$') or accessdate:match ('^%d%d?%s*%a+%s+%d%d%d%d$') then
local cap, cap2 = string.match (accessdate, '^(.*)%s+(%d%d%d%d)$');
accessdate = wrap_style ('nowrap2', {cap, cap2}); -- when accessdate is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY
end
accessdate = ' ' .. wrap_msg ('retrieved', accessdate, lower); -- add retrieved text
accessdate = wrap_style ('accessdate', {sepc, accessdate}); -- allow editors to hide accessdates
end
return accessdate;
end
--[[--------------------------< F O R M A T _ I D >----------------------------------------------------
]]
local function format_id (id, docket, sepc, lower)
id = pend_separator (id, sepc, true);
return pend_separator (wrap_msg ('docket', docket, lower), sepc, true) .. id;
end
--[[--------------------------< F O R M A T _ Q U O T E >----------------------------------------------
]]
local function format_quote (quote, sepc)
if is_set (quote) then
if quote:sub (1, 1) == '"' and quote:sub (-1, -1) == '"' then -- if first and last characters of quote are quote marks
quote = quote:sub (2, -2); -- strip them off
end
return pend_separator (wrap_style ('quoted-text', quote), sepc, true); -- wrap in <q>...</q> tags
end
return '';
end
--[[--------------------------< F O R M A T _ A R C H I V E >------------------------------------------
]]
local function format_archive (archive_url_object, original_url_object, archive_date, dead_url, sepc, lower)
local archived = '';
if is_set (archive_url_object['url']) then
if not is_set (archive_date) then
archive_date = set_error ('archive_missing_date');
end
if in_array (dead_url, cfg.keywords['deadurl-live']) then
local arch_text = cfg.messages['archived'];
if (lower) then arch_text = arch_text:lower(); end;
archived = pend_separator (wrap_msg ('archived-not-dead', {make_external_link (archive_url_object['url'], arch_text, archive_url_object['origin']) .. archive_url_object['format'], archive_date }, lower), sepc, true);
if not is_set (original_url_object['url']) then
archived = archived .. ' ' .. set_error ('archive_missing_url');
end
elseif is_set (original_url_object['url']) then -- dead_url is not live, so it should be empty, dead or unfit
if in_array (dead_url, cfg.keywords['deadurl-unfit']) then
archived = pend_separator (wrap_msg('archived-unfit', archive_date, lower), sepc, true);
-- format already styled
else -- dead_url is empty or dead
archived = pend_separator (wrap_msg ('archived-dead',
{make_external_link (original_url_object['url'], cfg.messages['original'], original_url_object['origin']) .. original_url_object['access-text'] .. original_url_object['format'], archive_date }, lower), sepc, true);
-- format already styled
end
else
archived = pend_separator (wrap_msg ('archived-missing',
{set_error ('archive_missing_url'), archive_date }, lower), sepc, true);
end
elseif is_set (original_url_object['format']) then
archived = original_url_object['format']; -- if set and archive_url not set archive_format has error message
end
return archived;
end
--[[--------------------------< F O R M A T _ L A Y >---------------------------------------------------
]]
local function format_lay (lay_url_object, lay_date, lay_source, sepc, lower)
local lay = '';
if is_set (lay_url_object['url']) then
if is_set (lay_date) then lay_date = ' (' .. lay_date .. ')' end
if is_set (lay_source) then
lay_source = wrap_msg ('lay source', lay_source, lower);
else
lay_source = '';
end
local lay_sum = cfg.messages['lay summary'];
if lower then
lay_sum = lay_sum:lower();
end
lay = pend_separator (make_external_link (lay_url_object['url'], lay_sum, lay_url_object['origin']) .. lay_url_object['format'] .. lay_source .. lay_date, sepc, true);
else -- Test if |lay-format= is given without giving a |lay-url=
lay = pend_separator (lay_url_object['format'], sepc, true); -- if set and LayURL not set, then LayFormat has error message
end
return lay;
end
--[[--------------------------< F O R M A T _ P E R I O D I C A L >------------------------------------
]]
local function format_periodical (periodical, title, title_note, sepc)
if is_set (periodical) then
if is_set (title) or is_set (title_note) then
return pend_separator (wrap_style ('italic-title', periodical), sepc, true);
else
return wrap_style ('italic-title', periodical);
end
end
return '';
end
--[[--------------------------< A N C H O R _ I D >------------------------------------------------------------
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise returns an empty string.
namelist is one of the contributor-, author-, or editor-name lists chosen in that order. year is Year or anchor_year.
]]
local function anchor_id (namelist, year)
local names={}; -- a table for the one to four names and year
for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names
names[i] = v.last
if i == 4 then break end -- if four then done
end
table.insert (names, year); -- add the year at the end
local id = table.concat (names); -- concatenate names and year for CITEREF id
if is_set (id) then -- if concatenation is not an empty string
return 'CITEREF' .. id; -- add the CITEREF portion
else
return ''; -- return an empty string; no reason to include CITEREF id in this citation
end
end
--[[--------------------------< F O R M A T _ C I T A T I O N >--------------------------------------------
]]
local function format_citation (body, cite_class, ref, namelist, year, ocins_output, no_tracking_cats)
local options = {};
if is_set (cite_class) and cite_class ~= 'citation' then
options.class = 'citation ' .. cite_class; -- class=citation required for blue highlight when used with |ref=
else
options.class = 'citation';
end
if is_set (ref) and ref:lower() ~= 'none' then -- set reference anchor if appropriate
local id = ref
if ('harv' == ref ) then
id = anchor_id (namelist, year); -- go make the CITEREF anchor
end
options.id = id;
end
if string.len (body:gsub ('<span[^>/]*>.-</span>', ''):gsub ('%b<>','')) <= 2 then
reset_error ({'err_cats'});
body = set_error ('empty_citation');
reset_error ({'msg_tail'});
end
local text;
if is_set (options.id) then
text = wrap_style ('citation-with-id', {mw.uri.anchorEncode (options.id), mw.text.nowiki (options.class), body});
else
text = wrap_style ('citation-no-id', {mw.text.nowiki (options.class), body});
end
text = text .. wrap_style ('OCinS', ocins_output);
text = text .. make_error_tail (no_tracking_cats); -- append error/maintenance messages/categories to the citation
return text;
end
--[[--------------------------< D E D U C E _ C I T A T I O N _ C L A S S >--------------------------------------
如果citation_class为citation({{citation}}),根据periodical系列参数的设置情况推断实际的引用类型。
]]
local function deduce_citation_class (A, naive_class)
local deduced_class;
local periodical = A['Periodical'];
local origin = A:ORIGIN ('Periodical');
for cite_class, aliases in pairs (cfg.periodical.parameters) do
if cite_class ~= '_general' then
for _, aliase in pairs (aliases) do
if origin == aliase then
deduced_class = cite_class;
end
end
end
end
if (naive_class == 'citation') then
if is_set (deduced_class) then
return deduced_class, true;
end
elseif (naive_class ~= deduced_class) then
local check_list = cfg.periodical.compatibility[naive_class];
if is_set (check_list) then
if is_set (check_list['drop']) and in_array (deduced_class, check_list['drop']) then
A['Periodical'] = discard_parameter (periodical, origin, nil);
elseif is_set (check_list['warn']) and in_array (deduced_class, check_list['warn']) then
append_error ('periodical', {origin, naive_class, deduced_class, check_list['suggest']});
end
end
end
return naive_class, false;
end
--[[--------------------------< A R G U M E N T _ W R A P P E R >----------------------------------------------
Argument wrapper. This function provides support for argument mapping defined in the configuration file so that
multiple names can be transparently aliased to single internal variable.
]]
local function argument_wrapper (args)
local origin = {};
return setmetatable ({
ORIGIN = function (self, k)
local dummy = self[k]; --force the variable to be loaded.
return origin[k];
end
},
{
__index = function (tbl, k)
if origin[k] ~= nil then
return nil;
end
local args, list, v = args, cfg.aliases[k];
if type (list) == 'table' then
v, origin[k] = select_one (args, list, 'redundant_parameters');
if origin[k] == nil then
origin[k] = ''; -- Empty string, not nil
end
elseif list ~= nil then
v, origin[k] = args[list], list;
else
-- maybe let through instead of raising an error?
-- v, origin[k] = args[k], k;
throw_error ('unknown_argument_map');
end
-- Empty strings, not nil;
if v == nil then
v = cfg.defaults[k] or '';
origin[k] = '';
end
tbl = rawset (tbl, k, v);
return v;
end,
});
end
--[[--------------------------< D O _ C I T A T I O N >---------------------------------------------------------
This is the main function doing the majority of the citation formatting.
]]
local function do_citation (config, args)
--local variables that are not cs1 parameters
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language
--[[
Load Input Parameters
The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.
]]
local A = argument_wrapper (args);
local citation_class, did_duduction = deduce_citation_class (A, config.CitationClass);
-- Pick out the relevant fields from the arguments. Different citation templates
-- define different field names for the same underlying things.
------------------------------------------------- Get dates
local Year = A['Year'];
local PublicationDate = A['PublicationDate'];
local OrigYear = A['OrigYear'];
local Date = A['Date'];
local Dateorigin = A:ORIGIN ('Date');
local LayDate = A['LayDate'];
------------------------------------------------- Get title data
local Title = A['Title'];
local ScriptTitle = A['ScriptTitle'];
local Conference = A['Conference'];
local TransTitle = A['TransTitle'];
local TitleNote = A['TitleNote'];
local TitleLink = A['TitleLink'];
local TitleLinkorigin = A:ORIGIN ('TitleLink');
local Periodical = A['Periodical'];
local Periodical_origin = A:ORIGIN ('Periodical'); -- get the name of the periodical parameter
local Series = A['Series'];
local ConferenceURLobject = create_url_object (A['ConferenceURL'], A:ORIGIN ('ConferenceURL'), A['ConferenceFormat'], A:ORIGIN ('ConferenceFormat'));
local ArchiveURLobject = create_url_object (A['ArchiveURL'], A:ORIGIN ('ArchiveURL'), A['ArchiveFormat'], A:ORIGIN ('ArchiveFormat'));
local URLobject = create_url_object (A['URL'], A:ORIGIN ('URL'), A['Format'], A:ORIGIN ('Format'),A['UrlAccess'], A:ORIGIN ('UrlAccess'));
local TranscriptURLobject = create_url_object (A['TranscriptURL'], A:ORIGIN ('TranscriptURL'), A['TranscriptFormat'], A:ORIGIN ('TranscriptFormat'));
local LayURLobject = create_url_object (A['LayURL'], A:ORIGIN ('LayURL'), A['LayFormat'], A:ORIGIN ('LayFormat'));
local Volume = A['Volume'];
local Issue = A['Issue'];
local Page = A['Page'];
local Pages = hyphen_to_dash (A['Pages']);
local At = A['At'];
if not in_array (citation_class, cfg.args_support['templates_using_volume']) then
Volume = discard_parameter (Volume, A:ORIGIN ('Volume'), nil);
end
if not in_array (citation_class, cfg.args_support['templates_using_issue']) then
if (A:ORIGIN ('Issue') ~= 'number') then
Issue = discard_parameter (Issue, A:ORIGIN ('Issue'), nil);
else
Issue = nil;
end
end
if in_array (citation_class, cfg.args_support['templates_not_using_page']) then
Page = discard_parameter (Page, A:ORIGIN ('Page'), nil);
Pages = discard_parameter (Pages, A:ORIGIN ('Pages'), nil);
At = discard_parameter (At, A:ORIGIN ('At'), nil);
end
local Minutes = A['Minutes'];
local Time = A['Time'];
local TimeCaption = A['TimeCaption'];
if not in_array (citation_class, cfg.args_support['templates_involving_time']) then
Minutes = discard_parameter (Minutes, A:ORIGIN ('Minutes'), nil);
Time = discard_parameter (Time, A:ORIGIN ('Time'), nil);
TimeCaption = discard_parameter (TimeCaption, A:ORIGIN ('TimeCaption'), nil);
end
local Sheet = A['Sheet'];
local Sheets = A['Sheets'];
local Section = A['Section'];
local Sections = A['Sections'];
local Inset = A['Inset'];
if not ('map' == citation_class) then
Sheet = discard_parameter (Sheet, A:ORIGIN ('Sheet'), nil);
Sheets = discard_parameter (Sheets, A:ORIGIN ('Sheets'), nil);
Sections = discard_parameter (Sections, A:ORIGIN ('Sections'), nil);
Inset = discard_parameter (Inset, A:ORIGIN ('Inset'), nil);
end
--[[
不知道哪个“天才”想出来的点子,现行引用模板里,section一个参数多个涵义。
在书籍类引用中,section是章节名称,在地图引用中,section是地图的区域编号。
所以一旦知道citation_class不是地图,就可以丢弃上述几乎全部参数,
唯独section参数需要留到检查章节相关参数时一并进行检查。
]]
local Chapter = '';
local ScriptChapter = '';
local TransChapter = '';
local ChapterURLobject;
local no_chapter_format = in_array (citation_class, cfg.args_support['templates_not_using_chapter_format']);
if in_array (citation_class, cfg.args_support['templates_not_using_chapter']) then
ChapterURLobject = create_url_object ();
discard_chapter (A);
if not ('map' == citation_class) then
Section = discard_parameter (Section, A:ORIGIN ('Section'), nil);
end
else
Chapter = A['Chapter'];
ScriptChapter = A['ScriptChapter'];
TransChapter = A['TransChapter'];
ChapterURLobject = create_url_object (A['ChapterURL'], A:ORIGIN ('ChapterURL'), A['ChapterFormat'], A:ORIGIN ('ChapterFormat'), A['ChapterUrlAccess'], A:ORIGIN ('ChapterUrlAccess'));
if is_set (Chapter) then
if is_set (Section) then
select_one (args, {'chapter', 'contribution', 'section'}, 'redundant_parameters');
end
else
Chapter = Section;
Section = nil;
end
end
local Edition = A['Edition'];
local PublicationPlace = A['PublicationPlace']
local Place = A['Place'];
local PublisherName = A['PublisherName'];
local RegistrationRequired = sanitized_parameter_value (A['RegistrationRequired'], A:ORIGIN ('RegistrationRequired'), 'yes_true_y', nil);
local SubscriptionRequired = sanitized_parameter_value (A['SubscriptionRequired'], A:ORIGIN ('SubscriptionRequired'), 'yes_true_y', nil);
local Via = A['Via'];
local AccessDate = A['AccessDate'];
local ArchiveDate = A['ArchiveDate'];
local Agency = A['Agency'];
local DeadURL = sanitized_parameter_value (A['DeadURL'], A:ORIGIN ('DeadURL'), 'deadurl', '');
local Language = A['Language'];
local DoiBroken = A['DoiBroken'];
local ID = A['ID'];
local ASINTLD = A['ASINTLD'];
local IgnoreISBN = sanitized_parameter_value (A['IgnoreISBN'], A:ORIGIN ('IgnoreISBN'), 'yes_true_y', nil);
local Embargo = A['Embargo'];
local Class = A['Class']; -- arxiv class identifier
local ID_list = extract_ids (args);
local ID_access_levels = extract_id_access_levels (args, ID_list);
local LaySource = A['LaySource'];
local Transcript = A['Transcript'];
local no_tracking_cats = set_no_tracking_cats (A['NoTracking'], A:ORIGIN ('NoTracking'), this_page);
local Quote = A['Quote'];
local sepc, PostScript, Ref = set_style (A['Mode'], A:ORIGIN ('Mode'), A['PostScript'], A['Ref'], Quote, config.CitationClass);
if is_set (Quote) and is_set (A['PostScript']) then
select_one (args, {'postscript', 'quote', 'quotation'}, 'redundant_parameters');
end
local use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text
-- check for insource-location-related parameters like |page=, |pages= or |at=. 请注意section参数有歧义,如果section跟书有关系,上面已经被清空了,这里不纳入检查。
select_one (args, {'at', 'time', 'minutes'}, 'redundant_parameters');
select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'time', 'minutes', 'sheet', 'sheets'}, 'redundant_parameters');
if is_set (Section) then
select_one (args, {'at', 'section', 'sections'}, 'redundant_parameters');
else
select_one (args, {'at', 'sections'}, 'redundant_parameters');
end
-- Dummy calls simply to get the error messages and categories
local NoPP = sanitized_parameter_value (A['NoPP'], A:ORIGIN ('NoPP'), 'yes_true_y', nil);
if is_set (Page) then
if is_set (Pages) or is_set (At) then
Pages = ''; -- unset the others
At = '';
end
extra_text_in_parameter_check (Page, 'page'); -- add this page to maint cat if |page= value begins with what looks like p. or pp.
elseif is_set (Pages) then
if is_set (At) then
At = ''; -- unset
end
extra_text_in_parameter_check (Pages, 'page'); -- add this page to maint cat if |pages= value begins with what looks like p. or pp.
end
-- both |publication-place= and |place= (|location=) allowed if different
if not is_set (PublicationPlace) and is_set (Place) then
PublicationPlace = Place; -- promote |place= (|location=) to |publication-place
end
if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same
if is_set (Edition) then
extra_text_in_parameter_check (Edition, 'edition');
end
------------------------------------------------- Get people
local NameListFormat = sanitized_parameter_value (A['NameListFormat'], A:ORIGIN ('NameListFormat'), 'name-list-format', '');
local LastAuthorAmp = sanitized_parameter_value (A['LastAuthorAmp'], A:ORIGIN ('LastAuthorAmp'), 'yes_true_y', nil);
local contributors_valid = in_array (citation_class, cfg.args_support['templates_using_contributor']);
local Authors, Contributors, Editors, Translators, Contribution, NameList, multiple_editors, has_contributors =
get_people (
{
vauthors = A['Vauthors'], authors = A['Authors'], veditors = A['Veditors'], editors = A['Editors'], contribution = A['Contribution'], coauthors = A['Coauthors']
}, {
displayauthors = A['DisplayAuthors'], displayeditors = A['DisplayEditors'], contributorsvalid = contributors_valid, namelistformat = NameListFormat, lastauthoramp = LastAuthorAmp
}, args, this_page.name
); -- (co-)authors, contributors, editors and translators
local TitleType = set_titletype (citation_class, A['TitleType']); -- handle type parameter for those CS1 citations that have default values
-- special case for cite thesis
local Degree = A['Degree'];
if 'thesis' == citation_class then
if (is_set (Degree)) then
TitleType = wrap_msg ('thesis with type', Degree, use_lowercase);
else
TitleType = wrap_msg ('thesis no type', 'placeholder', use_lowercase);
end
else
Degree = discard_parameter (Degree, A:ORIGIN ('Degree'), nil);
end
local Others = A['Others'];
--[[
Parameter remapping for cite encyclopedia:
When the citation has these parameters:
|encyclopedia and |title then map |title to |article and |encyclopedia to |title
|encyclopedia and |article then map |encyclopedia to |title
|encyclopedia then map |encyclopedia to |title
|trans_title maps to |trans_chapter when |title is re-mapped
|url maps to |chapterurl when |title is remapped
All other combinations of |encyclopedia, |title, and |article are not modified
]]
local Encyclopedia;
local Entry = A['Entry'];
if (citation_class == 'encyclopaedia') then -- test code for citation
local entry_redundant = false
Encyclopedia = Periodical;
if is_set (Periodical) then
if is_set (Title) or is_set (ScriptTitle) then
Chapter = Title;
ScriptChapter = ScriptTitle;
ScriptTitle = '';
TransChapter = TransTitle;
TransTitle = '';
ChapterURLobject = URLobject;
URLobject = create_url_object ();
if not is_set (ChapterURLobject['url']) and is_set (TitleLink) then
Chapter = make_internal_link (TitleLink, Chapter, TitleLinkorigin);
end
TitleLink = '';
entry_redundant = is_set (Entry);
elseif is_set (Entry) then
Chapter = Entry;
ChapterURLobject = URLobject;
URLobject = create_url_object ();
end
Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
Periodical = ''; -- redundant so unset
else
if is_set (Title) or is_set (ScriptTitle) then
entry_redundant = is_set (Entry);
else
Title = Entry;
end
end
if entry_redundant then
select_one (args, {'title', 'script-title', 'article', 'entry'}, 'redundant_parameters');
end
else
Entry = discard_parameter (Entry, A:ORIGIN ('Entry'), nil);
end
-- Special case for cite report.
local Docket = A['Docket'];
if citation_class == 'report' then
if is_set (Docket) then
if is_set (ID) then
select_one (args, {'id', 'docket'}, 'redundant_parameters');
end
ID = Docket; -- for cite report when |docket= is set, overwrite ID even if |id= is set
Docket = '';
end
elseif citation_class ~= 'thesis' then
discard_parameter (Docket, A:ORIGIN ('Docket'), '');
end
-- Special case for cite techreport.
local Num = A['Number'];
if citation_class == 'techreport' then -- special case for cite techreport
if is_set (Num) then -- cite techreport uses 'number', which other citations alias to 'issue'
if not is_set (ID) then -- can we use ID for the "number"?
ID = Num; -- yes, use it
else -- ID has a value so emit error message
select_one (args, {'id', 'number'}, 'redundant_parameters');
end
end
elseif not is_set (Issue) then
Num = discard_parameter (Num, A:ORIGIN ('Number'), nil);
end
-- special case for cite interview
local Callsign = A['Callsign'];
local City = A['City'];
local Program = A['Program'];
if (citation_class == 'interview') then
if is_set (Program) then
ID = ' ' .. Program;
end
if is_set (Callsign) then
if is_set (ID) then
ID = ID .. pend_separator (Callsign, sepc, true);
else
ID = ' ' .. Callsign;
end
end
if is_set (City) then
if is_set (ID) then
ID = ID .. pend_separator (City, sepc, true);
else
ID = ' ' .. City;
end
end
if is_set (Others) then
Others = wrap_msg ('interview', {TitleType, Others}, use_lowercase);
TitleType = '';
end
else
Callsign = discard_parameter (Callsign, A:ORIGIN ('Callsign'), nil );
City = discard_parameter (City, A:ORIGIN ('City'), nil );
Program = discard_parameter (Program, A:ORIGIN ('Program'), nil);
end
if is_set (TitleType) then -- if type parameter is specified
TitleType = wrap_msg ('type', TitleType, use_lowercase); -- display it in parentheses
end
-- Account for the oddity that is {{cite conference}} or {{cite speech}}.
local BookTitle = A['BookTitle'];
if 'conference' == citation_class then
if is_set (BookTitle) then
ChapterURLobject = URLobject;
URLobject = create_url_object ();
TransChapter = TransTitle;
TransTitle = '';
Chapter = Title;
Title = BookTitle;
end
else
BookTitle = discard_parameter (BookTitle, A:ORIGIN ('BookTitle'), nil);
if 'speech' == citation_class then
TitleNote = discard_parameter (TitleNote, A:ORIGIN ('TitleNote'), TitleType);
-- override whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).
TitleType = ''; -- annotate the citation
else
Conference = discard_parameter (Conference, A:ORIGIN ('Conference'), '');
-- not cite conference or cite speech so make sure this is empty string
end
end
-- cite map oddities
local Cartography = A['Cartography'];
local Scale = A['Scale'];
if citation_class == 'map' then
Chapter = A['Map'];
TransChapter = A['TransMap'];
ChapterURLobject = create_url_object (A['MapURL'], A:ORIGIN ('MapURL'), A['MapFormat'], A:ORIGIN ('MapFormat'), A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'));
Cartography = pend_separator (wrap_msg ('cartography', Cartography, use_lowercase), sepc, true);
Scale = pend_separator (Scale, sepc, true);
else
Cartography = discard_parameter (Cartography, A:ORIGIN ('Cartography'), '');
Scale = discard_parameter (Scale, A:ORIGIN ('Scale'), '');
discard_parameter (A['Map'], A:ORIGIN ('Map'), nil);
discard_parameter (A['MapURL'], A:ORIGIN ('MapURL'), nil);
discard_parameter (A['TransMap'], A:ORIGIN ('TransMap'), nil);
discard_parameter (A['MapFormat'], A:ORIGIN ('MapFormat'), nil);
discard_parameter (A['MapUrlAccess'], A:ORIGIN ('MapUrlAccess'), nil);
end
-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.
if 'episode' == citation_class or 'serial' == citation_class then
local AirDate = A['AirDate'];
local SeriesLink = A['SeriesLink'];
local Network = A['Network'];
local Station = A['Station'];
local s, n = {}, {};
-- do common parameters first
if is_set (Network) then table.insert (n, Network); end
if is_set (Station) then table.insert (n, Station); end
ID = table.concat (n, sepc .. ' ');
if is_set (AirDate) then
if not is_set (Date) then -- promote airdate to date
Date = AirDate;
Dateorigin = A:ORIGIN ('AirDate');
else
select_one (args, {'date', 'air-date', 'airdate'}, 'redundant_parameters');
end
end
if 'episode' == citation_class then -- handle the oddities that are strictly {{cite episode}}
local Season = A['Season'];
local SeriesNumber = A['SeriesNumber'];
if is_set (Season) and is_set (SeriesNumber) then -- these are mutually exclusive so if both are set
select_one (args, {'season', 'series-number', 'series-no', 'seriesnumber', 'seriesno'}, 'redundant_parameters');
-- add error message
SeriesNumber = ''; -- unset; prefer |season= over |seriesno=
end
-- assemble a table of parts concatenated later into Series
if is_set (Season) then table.insert (s, wrap_msg ('season', Season, use_lowercase)); end
if is_set (SeriesNumber) then table.insert (s, wrap_msg ('series', SeriesNumber, use_lowercase)); end
if is_set (Issue) then table.insert (s, wrap_msg ('episode', Issue, use_lowercase)); end
Issue = ''; -- unset because this is not a unique parameter
Chapter = Title; -- promote title parameters to chapter
ScriptChapter = ScriptTitle;
local ChapterLink = TitleLink; -- alias episodelink
local ChapterLinkorigin = TitleLinkorigin;
TransChapter = TransTitle;
ChapterURLobject = URLobject;
Title = Series; -- promote series to title
TitleLink = SeriesLink;
TitleLinkorigin = A:ORIGIN ('SeriesLink');
Series = table.concat (s, sepc .. ' '); -- this is concatenation of season, seriesno, episode number
if is_set (ChapterLink) and not is_set (ChapterURL) then -- link but not URL
Chapter = make_internal_link (ChapterLink, Chapter, ChapterLinkorigin);
-- ok to wikilink
elseif is_set (ChapterLink) and is_set (ChapterURL) then -- if both are set, URL links episode;
Series = make_internal_link (ChapterLink, Series, ChapterLinkorigin);
-- series links with ChapterLink (episodelink -> TitleLink -> ChapterLink) ugly
end
URLobject = create_url_object (); -- unset
TransTitle = '';
ScriptTitle = '';
else -- now oddities that are cite serial
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
if is_set (Series) and is_set (SeriesLink) then
Series = make_internal_link (SeriesLink, Series, A:ORIGIN ('SeriesLink'));
end
Series = wrap_style ('italic-title', Series); -- series is italicized
end
end
-- end of {{cite episode}} stuff
-- Account for the oddities that are {{cite arxiv}}, before generation of COinS data.
if 'arxiv' == citation_class then
if not is_set (ID_list['ARXIV']) then -- |arxiv= or |eprint= required for cite arxiv
append_error ('arxiv_missing', {}); -- add error message
elseif is_set (Series) then -- series is an alias of version
ID_list['ARXIV'] = ID_list['ARXIV'] .. Series; -- concatenate version onto the end of the arxiv identifier
Series = ''; -- unset
deprecated_parameter ('version'); -- deprecated parameter but only for cite arxiv
end
if first_set ({AccessDate, At, URLobject['format'], Page, Pages, PublisherName, URLobject['url'], -- a crude list of parameters that are not supported by cite arxiv
ID_list['ASIN'], ID_list['BIBCODE'], ID_list['DOI'], ID_list['ISBN'], ID_list['ISSN'],
ID_list['JFM'], ID_list['JSTOR'], ID_list['LCCN'], ID_list['MR'], ID_list['OCLC'], ID_list['OL'],
ID_list['OSTI'], ID_list['PMC'], ID_list['PMID'], ID_list['RFC'], ID_list['SSRN'], ID_list['USENETID'], ID_list['ZBL']},27) then
append_error ('arxiv_params_not_supported', {}); -- add error message
AccessDate= ''; -- set these to empty string; not supported in cite arXiv
PublisherName = ''; -- (if the article has been published, use cite journal, or other)
URLobject = create_url_object ();
Page = ''; Pages = ''; At = '';
end
Periodical = 'arXiv'; -- periodical not allowed in cite arxiv; if article has been published, use cite journal
-- set to arXiv for COinS; after that, must be set to empty string
end
-- legacy: promote concatenation of |month=, and |year= to Date if Date not set; or, promote PublicationDate to Date if neither Date nor Year are set.
if not is_set (Date) then
if is_set (Year) then
Date = Year;
Dateorigin = A:ORIGIN ('Year'); -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
elseif is_set (PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate;
Dateorigin = A:ORIGIN ('PublicationDate'); -- promote PublicationDate to Date
PublicationDate = '';
end
else
if is_set (PublicationDate) and PublicationDate ~= Date then
PublicationDate = wrap_msg ('publication-date', PublicationDate, use_lowercase);
else
PublicationDate = ''; -- if PublicationDate is same as Date, don't display in rendered citation
end
end
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification
local anchor_year = validate_date (AccessDate, ArchiveDate, Date, DoiBroken, Embargo, LayDate, PublicationDate, Year, COinS_date, Dateorigin);
-- used in the CITEREF identifier
-- Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set. Do this after date check but before COInS.
-- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date
Embargo = is_embargoed (Embargo); --
if citation_class == 'journal' and not is_set (URLobject['url']) and is_set (ID_list['PMC']) then
if not is_set (Embargo) then -- if not embargoed or embargo has expired
URLobject['url'] =cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed
URLobject['origin'] = cfg.id_handlers['PMC'].parameters[1]; -- set URLorigin to parameter name for use in error message if citation is missing a |title=
end
end
if not is_set (URLobject['url']) then
if in_array (citation_class, cfg.args_support['templates_requiring_url']) then
append_error ('cite_web_url', {});
end
-- Test if accessdate is given without giving a URL
if is_set (AccessDate) and not is_set (ChapterURLobject['url']) then -- ChapterURL may be set when the others are not set; TODO: move this to a separate test?
append_error ('accessdate_missing_url', {});
AccessDate = '';
end
end
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact.
-- Test if citation has no title
if not is_set (Title) and
not is_set (TransTitle) and
not is_set (ScriptTitle) then
if 'episode' == citation_class then -- special case for cite episode; TODO: is there a better way to do this?
append_error ('citation_missing_title', {'series'});
else
append_error ('citation_missing_title', {'title'});
end
end
if 'none' == Title and citation_class == 'journal' then -- special case for journal cites
Title = ''; -- set title to empty string
add_maint_cat ('untitled');
end
check_for_external_link ({ -- add error message when any of these parameters contains a URL
['title'] = Title,
[A:ORIGIN ('Chapter')] = Chapter,
[A:ORIGIN ('Periodical')] = Periodical,
[A:ORIGIN ('PublisherName')] = PublisherName,
});
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
-- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that
-- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title
-- is the article title, and Chapter is a section within the article. So, we remap
local coins_chapter = Chapter; -- default assuming that remapping not required
local coins_title = Title; -- et tu
if 'encyclopaedia' == citation_class then
if is_set (Chapter) and is_set (Title) and is_set (Periodical) then -- if all are used then
coins_chapter = Title; -- remap
coins_title = Periodical;
end
end
-- this is the function call to COinS()
local OCinSoutput = COinS ({
['Periodical'] = Periodical,
['Encyclopedia'] = Encyclopedia,
['Chapter'] = coins_chapter,
['ScriptChapter'] = ScriptChapter,
['Map'] = Map,
['Degree'] = Degree; -- cite thesis only
['Title'] = coins_title,
['ScriptTitle'] = ScriptTitle,
['PublicationPlace'] = PublicationPlace,
['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid;
['Season'] = COinS_date.rftssn,
['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit?
['Series'] = Series,
['Volume'] = Volume,
['Issue'] = Issue,
['Pages'] = first_set ({Sheet, Sheets, Page, Pages, At}, 5),
['Edition'] = Edition,
['PublisherName'] = PublisherName,
['URL'] = first_set ({ChapterURLobject['url'], URLobject['url']}, 2),
['Authors'] = NameList,
['ID_list'] = ID_list,
['RawPage'] = this_page.prefixedText,
}, config.CitationClass);
-- Account for the oddities that are {{cite arxiv}}, AFTER generation of COinS data.
if 'arxiv' == citation_class then -- we have set rft.jtitle in COinS to arXiv, now unset so it isn't displayed
Periodical = '';
end
-- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text
if 'newsgroup' == citation_class then
if is_set (PublisherName) then
PublisherName = wrap_msg ('newsgroup', make_external_link ('news:' .. PublisherName, PublisherName, A:ORIGIN ('PublisherName')), use_lowercase);
end
end
-- Now perform various field substitutions.
-- We also add leading spaces and surrounding markup and punctuation to the
-- various parts of the citation, but only when they are non-nil.
-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,
-- an error message if the associated url is not set, or an empty string for concatenation
format_format ({ArchiveURLobject, ConferenceURLobject, URLobject, LayURLobject, TranscriptURLobject, ChapterURLobject});
-- special case for chapter format so no error message or cat when chapter not supported
if format_url_access_text (URLobject, SubscriptionRequired, RegistrationRequired) then
select_one (args, {'url-access', 'urlaccess', 'registration', 'subscription'}, 'redundant_parameters');
end -- 只需其一
format_url_access_text (ChapterURLobject, nil, nil);
local OriginalURLobject; -- TODO: swap chapter and title here so that archive applies to most specific if both are set?
OriginalURLobject, URLobject, ChapterURLobject =
swap_urls (URLobject, ChapterURLobject, ArchiveURLobject, DeadURL);
local chapter_no_quotes = false; -- default assume that we will be quoting the chapter parameter value
if is_set (Contribution) and has_contributors then -- if this is a contribution with contributor(s)
if in_array (Contribution:lower(), cfg.keywords['contribution']) then -- and a generic contribution title
chapter_no_quotes = true; -- then render it unquoted
end
end
Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURLobject, chapter_no_quotes, citation_class, TitleType, sepc);
-- Contribution is also in Chapter
-- Format main title.
Title, URLobject = format_main_title (Title, TitleLink, TitleLinkorigin, ScriptTitle, TransTitle, URLobject, no_chapter_format, citation_class, Periodical);
Place = pend_separator (wrap_msg ('written', Place, use_lowercase), sepc, false);
Conference = format_conference (Conference, ConferenceURLobject, Periodical, citation_class, sepc);
local Insource_location = format_insource_location (Page, Pages, Sheet, Sheets, At, Minutes, Time, TimeCaption, Section, Sections, Inset, citation_class, Periodical_origin, sepc, NoPP, use_lowercase);
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc
Others = pend_separator (Others, sepc, true);
Others = pend_separator (wrap_msg ('translated', Translators, use_lowercase), sepc, true) .. Others;
if 'speech' ~= citation_class then
TitleNote = pend_separator (TitleNote, sepc, true);
end
Edition = wrap_msg ('edition', Edition, use_lowercase);
Series = pend_separator (Series, sepc, true);
OrigYear = wrap_msg ('orig year', OrigYear, use_lowercase);
Agency = pend_separator (Agency, sepc, true);
Volume = format_volume_issue (Volume, Issue, citation_class, Periodical_origin, sepc, use_lowercase);
------------------------------------ totally unrelated data
Via = wrap_msg ('via', Via, use_lowercase);
AccessDate = format_accessdate (AccessDate, sepc, use_lowercase);
ID = format_id (ID, Docket, sepc, use_lowercase);
ID_list = build_id_list (ID_list, {IdAccessLevels=ID_access_levels, DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo, Class = Class});
local URL = '';
if is_set (URLobject['url']) then
URL = ' ' .. make_external_link (URLobject['url'], nil, URLobject['origin']) .. URLobject['access-text'];
end
local Format = URLobject['format'];
Quote = format_quote (Quote, sepc);
local Archived = format_archive (ArchiveURLobject, OriginalURLobject, ArchiveDate, DeadURL, sepc, use_lowercase);
local Lay = format_lay (LayURLobject, LayDate, LaySource, sepc, use_lowercase);
Transcript = format_external_link (Transcript, TranscriptURLobject, sepc);
local Publisher = format_publisher (PublisherName, PublicationPlace, Periodical, citation_class, sepc);
local use_in = is_set (Chapter) and (not has_contributors);
Authors, Editors, Contributors = format_people (Authors, Editors, Contributors, multiple_editors, use_in, sepc);
-- Several of the above rely upon detecting this as nil, so do it last.
Periodical = format_periodical (Periodical, Title, TitleNote, sepc);
-- Piece all bits together at last. Here, all should be non-nil.
-- We build things this way because it is more efficient in LUA
-- not to keep reassigning to the same string variable over and over.
local tcommon;
local tcommon2; -- used for book cite when |contributor= is set
if citation_class == 'journal' and is_set (Periodical) then
Others = pend_separator (Others, sepc, false);
tcommon = safe_join ({Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Edition, Publisher, Agency}, sepc);
elseif contributors_valid then -- special cases for book cites where contributors are allowed
if is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc
tcommon = safe_join ({Title, TitleNote}, sepc); -- author and other stuff will come after this and before tcommon2
tcommon2 = safe_join ({Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
else
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
end
elseif 'map' == citation_class then -- special cases for cite map
if is_set (Chapter) then -- map in a book; TitleType is part of Chapter
tcommon = safe_join ({Title, Format, Edition, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
elseif is_set (Periodical) then -- map in a periodical
tcommon = safe_join ({Title, TitleType, Format, Periodical, Scale, Series, Cartography, Others, Publisher, Volume}, sepc);
else -- a sheet or stand-alone map
tcommon = safe_join ({Title, TitleType, Format, Edition, Scale, Series, Cartography, Others, Publisher}, sepc);
end
elseif 'episode' == citation_class then -- special case for cite episode
tcommon = safe_join ({Title, TitleNote, TitleType, Series, Transcript, Edition, Publisher}, sepc);
else -- all other CS1 templates
tcommon = safe_join ({Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Volume, Others, Edition, Publisher, Agency}, sepc);
end
if #ID_list > 0 then
ID_list = safe_join ({sepc .. ' ', table.concat (ID_list, sepc .. ' '), ID}, sepc);
else
ID_list = ID;
end
-- LOCAL
local xDate;
if (is_set (Periodical) and is_set (Date) and
not in_array (citation_class, {'encyclopaedia', 'web'}))
or (in_array (citation_class, {'book', 'news'})) then
if in_array (citation_class, {'journal', 'citation'}) and is_set (Volume) then
xDate = safe_join ({Date .. ',' .. Volume, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
else
xDate = safe_join ({Date, Insource_location, PublicationDate, OrigYear, AccessDate}, sepc);
end
Insource_location = ''
else
xDate = safe_join ({Date, PublicationDate, OrigYear, AccessDate}, sepc);
end
xDate = pend_separator (xDate, sepc, true);
-- END LOCAL
local idcommon = safe_join ({URL, xDate, ID_list, Archived, Via, Lay, Language, Quote}, sepc);
local text;
if is_set (Authors) then
if is_set (Contributors) then
text = safe_join ({Contributors, Chapter, tcommon, Authors, Place, Editors, tcommon2, Insource_location, idcommon }, sepc);
else
text = safe_join ({Authors, Chapter, Place, Editors, tcommon, Insource_location, idcommon }, sepc);
end
else
text = safe_join ({Editors, Chapter, Place, tcommon, Insource_location, idcommon}, sepc);
end
if is_set (PostScript) and PostScript ~= sepc then
text = safe_join ({text, sepc}, sepc); --Deals with italics, spaces, etc.
text = text:sub (1, -sepc:len()-1);
end
text = safe_join ({text, PostScript}, sepc);
-- Now enclose the whole thing in a <cite/> element
return format_citation (text, config.CitationClass, Ref, NameList, anchor_year, OCinSoutput, no_tracking_cats);
end
--[[--------------------------< V A L I D A T E >--------------------------------------------------------------
Looks for a parameter's name in the whitelist.
Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
local function validate (name)
local name = tostring (name);
local state = whitelist.basic_arguments[name];
-- Normal arguments
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
-- Arguments with numbers in them
name = name:gsub ('%d+', '#'); -- replace digit(s) with # (last25 becomes last#
state = whitelist.numbered_arguments[name];
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
return false; -- Not supported because not found or name is set to nil
end
--[[--------------------------< C I T A T I O N >--------------------------------------------------------------
This is used by templates such as {{cite book}} to create the actual citation text.
]]
function citation (frame)
local pframe = frame:getParent();
local module_path = 'Module:Citation/CS1/'
local module_suffix = frame:getTitle():gsub ('^Module:Citation/CS1', '');
load_modules (module_path, module_suffix);
local args = {};
local suggestions = {};
local error_reported = false;
local config = {};
for k, v in pairs (frame.args) do
config[k] = v;
args[k] = v;
end
local capture; -- the single supported capture when matching unknown parameters using patterns
for k, v in pairs (pframe.args) do
if v ~= '' then
if not validate (k) then
error_reported = false;
if type (k) ~= 'string' then
-- Exclude empty numbered parameters
if v:match ('%S+') ~= nil then
append_error ('text_ignored', {v});
error_reported = true;
end
elseif validate (k:lower()) then
append_error ('parameter_ignored_suggest', {k, k:lower()});
error_reported = true;
else
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData (module_path .. 'Suggestions' .. module_suffix);
end
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
capture = k:match (pattern); -- the whole match if no caputre in pattern else the capture if a match
if capture then -- if the pattern matches
param = substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
append_error ('parameter_ignored_suggest', {k, param});
-- set the error message
error_reported = true;
break;
end
end
if not error_reported then -- couldn't match with a pattern, is there an expicit suggestion?
if suggestions.suggestions[k:lower()] ~= nil then
append_error ('parameter_ignored_suggest', {k, suggestions.suggestions[k:lower()]});
error_reported = true;
else
append_error ('parameter_ignored', {k});
error_reported = true;
end
end
end
end
args[k] = v;
elseif args[k] ~= nil or (k == 'postscript') then
args[k] = v;
end
end
local error_msg;
for k, v in pairs (args) do
if 'string' == type (k) then -- don't evaluate positional parameters
error_msg = has_invisible_chars (k, v);
if is_set (error_msg) then
append_error ('invisible_char', error_msg);
end
end
end
return do_citation (config, args)
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {citation = citation};
c5e02f2cabbe93b86a6702b2d17ce44e5a0069d1
Module:Citation/CS1/Configuration
828
176
359
358
2024-08-04T12:21:56Z
黑茶
2
导入1个版本
Scribunto
text/plain
local citation_config = {};
-- override <code>...</code> styling to remove color, border, and padding. <code> css is specified here:
-- https://git.wikimedia.org/blob/mediawiki%2Fcore.git/69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199
local code_style="color:inherit; border:inherit; padding:inherit;";
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------
List of namespaces that should not be included in citation error categories. Same as setting notracking = true by default
Note: Namespace names should use underscores instead of spaces.
]]
local uncategorized_namespaces = { 'User', 'Talk', 'User_talk', 'Wikipedia_talk', 'File_talk', 'Template_talk',
'Help_talk', 'Category_talk', 'Portal_talk', 'Book_talk', 'Draft', 'Draft_talk', 'Education_Program_talk',
'Module_talk', 'MediaWiki_talk' };
local uncategorized_subpages = {'/[Ss]andbox', '/[Tt]estcases'}; -- list of Lua patterns found in page names of pages we should not categorize
--[[--------------------------< M E S S A G E S >--------------------------------------------------------------
Translation table
The following contains fixed text that may be output as part of a citation.
This is separated from the main body to aid in future translations of this
module.
]]
local messages = {
['_safe_for_italics'] = {'lay source'},
['archived-dead'] = '($1存档于$2)',
['archived-not-dead'] = '(原始内容$1于$2)',
['archived-missing'] = '(原始内容$1存档于$2)',
['archived-unfit'] = '原始内容存档于$1',
['archived'] = '存档',
['by'] = 'By', -- contributions to authored works: introduction, foreword, afterword
['cartography'] = 'Cartography by $1',
['docket'] = 'Docket $1',
['editor'] = '编',
['editors'] = '编',
['edition'] = ' $1',
['episode'] = '第$1集',
['et al'] = 'et al',
['in'] = '(编)', -- edited works
['inactive'] = '不活跃',
['interview'] = ' $1 with $2',
['inset'] = '$1 inset',
['lay summary'] = '简明摘要',
['lay source'] = " – ''$1''",
['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1',
['original'] = '原始内容',
['orig year'] = ' [$1]',
['published'] = '$1',
['retrieved'] = '[$1]',
['season'] = '第$1季',
['section'] = '§ $1',
['sections'] = '§§ $1',
['series'] = '第$1系列',
['thesis with type'] = '$1论文',
['thesis no type'] = '学位论文',
['translated'] = '由$1翻译',
['type'] = ' ($1)', -- for titletype
['written'] = ' 写于$1',
['vol'] = '$1 Vol. $2', -- $1 is sepc; bold journal style volume is in presentation{}
['vol-no'] = '$1 Vol. $2 no. $3', -- sepc, volume, issue
['issue'] = '$1 No. $2', -- $1 is sepc
['j-vol'] = '$1 $2', -- sepc, volume; bold journal volume is in presentation{}
['j-issue'] = ' ($1)',
['nopp'] = '$1 $2'; -- page(s) without prefix; $1 is sepc
['p-prefix'] = ": $2", -- $1 is sepc
['pp-prefix'] = ": $2", -- $1 is sepc
['j-page(s)'] = ': $1', -- same for page and pages
['sheet'] = '$1 Sheet $2', -- $1 is sepc
['sheets'] = '$1 Sheets $2', -- $1 is sepc
['j-sheet'] = ': Sheet $1',
['j-sheets'] = ': Sheets $1',
['language'] = '<span style="font-family: sans-serif; cursor: default; color:var(--color-subtle, #54595d); font-size: 0.8em; bottom: 0.1em; font-weight: bold;" title="连接到$1网页">($1)</span>',
['via'] = " –-{zh-hans:通过;zh-hant:透過;}-$1",
['event'] = ' 事件发生在 $1',
['minutes'] = ' $1 记录于',
['parameter-separator'] = '、',
['parameter-final-separator'] = '和',
['parameter-pair-separator'] = '和',
['publication-date'] = ' ($1)',
-- Determines the location of the help page
['help page link'] = 'Help:引文格式1错误',
['help page label'] = '帮助',
['maintenance-link'] = 'link',
['maintenance-item'] = ' $1 ($2)'
}
--[[--------------------------< I N T E R N A L _ E R R O R S >-------------------------------------------
Internal errors (should only occur if configuration is bad)
]]
local internal_errors = {
['undefined_error'] = '调用了一个未定义的错误条件',
['unknown_manual_ID'] = '无法识别的手动ID模式',
['unknown_ID_mode'] = '无法识别的ID模式',
['unknown_argument_map'] = '检测到参数别名与参数名之间的映射丢失',
['bad_link_no_origin'] = '检测到格式错误但源头不明的内部链接',
['bad_url_no_origin'] = '检测到格式错误但源头不明的网址',
['bare_url_no_origin'] = '检测到源头不明的裸网址',
}
--[[--------------------------< P R E S E N T A T I O N >------------------------------------------------------
Fixed presentation markup. Originally part of citation_config.messages it has been moved into its own, more semantically
correct place.
]]
local presentation = {
['_safe_for_italics'] = {'italic-title', 'trans-italic-title'},
-- Error output
-- .error class is specified at https://git.wikimedia.org/blob/mediawiki%2Fcore.git/9553bd02a5595da05c184f7521721fb1b79b3935/skins%2Fcommon%2Fshared.css#L538
-- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display
['hidden-error'] = '<span style="display:none;font-size:100%" class="error citation-comment">$1</span>',
['visible-error'] = '<span style="font-size:100%" class="error citation-comment">$1</span>',
['accessdate'] = ' <span class="reference-accessdate">$2</span>', -- to allow editors to hide accessdate using personal css
['bdi'] = '<bdi$1>$2</bdi>', -- bidirectional isolation used with |script-title= and the like
['format'] = ' <span style="font-size:85%;">($1)</span>', -- for |format=, |chapter-format=, etc
['access-signal'] = '<span class="plainlinks">$1 $2</span>', -- external link with appropriate lock icon
['free'] = '[[File:Lock-green.svg|9px|link=|alt=可免费查阅|可免费查阅]]',
['registration'] = '[[File:Lock-blue-alt-2.svg|9px|link=|alt=需要免费注册|需要免费注册]]',
['limited'] = '[[File:Lock-blue-alt-2.svg|9px|link=|alt=有限度免费查阅,超限则需付费订阅|有限度免费查阅,超限则需付费订阅]]',
['subscription'] = '[[File:Lock-red-alt.svg|9px|link=|alt=需要付费订阅|需要付费订阅]]',
['italic-title'] = "$1",
['kern-left'] = '<span style="padding-left:0.2em;">$1</span>$2', -- spacing to use when title contains leading single or double quote mark
['kern-right'] = '$1<span style="padding-right:0.2em;">$2</span>', -- spacing to use when title contains trailing single or double quote mark
['nowrap1'] = '<span class="nowrap">$1</span>', -- for nowrapping an item: <span ...>yyyy-mm-dd</span>
['nowrap2'] = '<span class="nowrap">$1</span> $2', -- for nowrapping portions of an item: <span ...>dd mmmm</span> yyyy (note white space)
['OCinS'] = '<span title="$1" class="Z3988"><span style="display:none;"> </span></span>',
-- Note: Using display: none on the COinS span breaks some clients.
['parameter'] = '<code style="'..code_style..'">|$1=</code>',
['quoted-text'] = '<q>$1</q>', -- for wrapping |quote= content
['quoted-title'] = '$1',
['trans-italic-title'] = "[$1]",
['trans-quoted-title'] = "[$1]",
['vol-bold'] = ' <b>$1</b>', -- for journal cites; for other cites ['vol'] in messages{}
['maintenance'] = '<span class="citation-comment" style="display:none; color:#33aa33">$1</span>',
['citation-with-id'] = '<cite id="$1" class="$2">$3</cite>',
['citation-no-id'] = '<cite class="$1">$2</cite>'
}
--[[--------------------------< P E R I O D I C A L _ P A R A M E T E R S >-----------------------------------
用于整理periodical系列参数的别名,key为对应的citation class。在主模块中推断{{citation}}的引用类型时会用到。
]]
local periodical_parameters = {
['journal'] = {'journal'},
['news'] = {'newspaper'},
['magazine'] = {'magazine'},
['web'] = {'website'},
['encyclopaedia'] = {'encyclopedia', 'encyclopaedia', 'dictionary'},
['mailinglist'] = {'mailinglist', 'mailing-list'},
['_general'] = {'work', 'periodical'}
} -- 注意参数排列顺序,_general一定要放最后。
local periodical_compatibility = {
['journal'] = {
['drop'] = {'news', 'encyclopaedia', 'mailinglist'},
['warn'] = {'magazine'},
['suggest'] = 'journal'
},
['news'] = {
['drop'] = {'encyclopaedia', 'mailinglist', 'journal'},
['warn'] = {'magazine'},
['suggest'] = 'newspaper'
},
['magazine'] = {
['drop'] = {'encyclopaedia', 'mailinglist'},
['warn'] = {'journal', 'news'},
['suggest'] = 'magazine'
},
['web'] = {
['drop'] = {'encyclopaedia', 'mailinglist'},
['warn'] = {'news', 'journal', 'magazine'},
['suggest'] = 'website'
},
['encyclopaedia'] = {
['drop'] = {'mailinglist', 'news', 'journal', 'magazine'},
},
['mailinglist'] = {
['drop'] = {'encyclopaedia', 'news', 'journal', 'magazine', 'web'},
},
['book'] = {
['drop'] = {'news', 'journal', 'mailinglist'},
['warn'] = {'encyclopaedia', 'magazine'},
['suggest'] = 'work'
},
['conference'] = {
['drop'] = {'news', 'magazine', 'mailinglist', 'encyclopaedia'},
['warn'] = {'journal'},
['suggest'] = 'book-title'
},
['map'] = {
['drop'] = {'mailinglist', 'encyclopaedia'},
},
['interview'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal'},
},
['AV media'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine'},
},
['podcast'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['serial'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['speech'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine'},
},
['episode'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'journal', 'magazine', 'news'},
},
['thesis'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'news'},
},
['pressrelease'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'journal'},
},
['arxiv'] = {
['drop'] = {'mailinglist', 'encyclopaedia', 'magazine', 'journal', 'web'}
}
}
local function build_periodical ()
local periodical_items = {};
for _, aliases in pairs (periodical_parameters) do
for _, aliase in pairs (aliases) do
table.insert (periodical_items, aliase);
end
end
return periodical_items;
end
local periodical = {
parameters = periodical_parameters,
compatibility = periodical_compatibility
}
--[[--------------------------< A L I A S E S >----------------------------------------------------------------
Aliases table for commonly passed parameters
]]
local aliases = {
['AccessDate'] = {'access-date', 'accessdate'},
['Agency'] = 'agency',
['AirDate'] = {'air-date', 'airdate'},
['ArchiveDate'] = {'archive-date', 'archivedate'},
['ArchiveFormat'] = 'archive-format',
['ArchiveURL'] = {'archive-url', 'archiveurl'},
['ASINTLD'] = {'ASIN-TLD', 'asin-tld'},
['At'] = 'at',
['Authors'] = {'authors', 'people', 'host', 'credits'},
['BookTitle'] = {'book-title', 'booktitle'},
['Callsign'] = {'call-sign', 'callsign'}, -- cite interview
['Cartography'] = 'cartography',
['Chapter'] = {'chapter', 'contribution'},
['ChapterFormat'] = {'chapter-format', 'contribution-format', 'section-format'};
['ChapterURL'] = {'chapter-url', 'chapterurl', 'contribution-url', 'contributionurl', 'section-url', 'sectionurl'},
['ChapterUrlAccess'] = {'chapter-url-access', 'section-url-access'};
['City'] = 'city', -- cite interview
['Class'] = 'class', -- cite arxiv and arxiv identifiers
['Coauthors'] = {'coauthors', 'coauthor'}, -- coauthor and coauthors are deprecated; remove after 1 January 2015?
['Conference'] = {'conference', 'event'},
['ConferenceFormat'] = {'conference-format', 'event-format'},
['ConferenceURL'] = {'conference-url', 'conferenceurl', 'event-url', 'eventurl'},
['Contribution'] = 'contribution', -- introduction, foreword, afterword, etc; required when |contributor= set
['Date'] = 'date',
['DeadURL'] = {'dead-url', 'deadurl','url-status','urlstatus'},
['Degree'] = 'degree',
['DF'] = 'df',
['DisplayAuthors'] = {'display-authors', 'displayauthors'},
['DisplayEditors'] = {'display-editors', 'displayeditors'},
['Docket'] = 'docket',
['DoiBroken'] = {'doi-broken', 'doi-broken-date', 'doi-inactive-date', 'doi_brokendate', 'doi_inactivedate'},
['Edition'] = 'edition',
['Editors'] = 'editors',
['Embargo'] = 'embargo',
['Entry'] = {'entry', 'article'}, -- cite encyclopedia only
['Episode'] = 'episode', -- cite serial only TODO: make available to cite episode?
['Format'] = 'format',
['ID'] = {'id', 'ID'},
['IgnoreISBN'] = {'ignore-isbn-error', 'ignoreisbnerror'},
['Inset'] = 'inset',
['Issue'] = {'issue', 'number'},
['Language'] = {'language', 'in'},
['LastAuthorAmp'] = {'last-author-amp', 'lastauthoramp'},
['LayDate'] = {'lay-date', 'laydate'},
['LayFormat'] = 'lay-format',
['LaySource'] = {'lay-source', 'laysource'},
['LayURL'] = {'lay-url', 'lay-summary', 'layurl', 'laysummary'},
['Map'] = 'map', -- cite map only
['MapFormat'] = 'map-format', -- cite map only
['MapURL'] = {'mapurl', 'map-url'}, -- cite map only
['MapUrlAccess'] = {'map-url-access'}, -- cite map only
['MessageID'] = 'message-id',
['Minutes'] = 'minutes',
['Mode'] = 'mode',
['NameListFormat'] = {'name-list-format','name-list-style'},
['Network'] = 'network',
['NoPP'] = {'no-pp', 'nopp'},
['NoTracking'] = {'template-doc-demo', 'template doc demo', 'no-cat', 'nocat',
'no-tracking', 'notracking'},
['Number'] = 'number', -- this case only for cite techreport
['OrigYear'] = {'orig-year', 'origyear'},
['Others'] = {'others', 'interviewer', 'interviewers'},
['Page'] = {'p', 'page'},
['Pages'] = {'pp', 'pages'},
['Periodical'] = build_periodical (),
['Place'] = {'place', 'location'},
['Program'] = 'program', -- cite interview
['PostScript'] = 'postscript',
['PublicationDate'] = {'publicationdate', 'publication-date'},
['PublicationPlace'] = {'publication-place', 'publicationplace'},
['PublisherName'] = {'publisher', 'distributor', 'institution', 'newsgroup'},
['Quote'] = {'quote', 'quotation'},
['Ref'] = 'ref',
['RegistrationRequired'] = 'registration',
['Scale'] = 'scale',
['ScriptChapter'] = 'script-chapter',
['ScriptTitle'] = 'script-title',
['Section'] = 'section',
['Sections'] = 'sections', -- cite map only
['Season'] = 'season',
['Series'] = {'series', 'version'},
['SeriesSeparator'] = 'series-separator',
['SeriesLink'] = {'series-link', 'serieslink'},
['SeriesNumber'] = {'series-number', 'series-no', 'seriesnumber', 'seriesno'},
['Sheet'] = 'sheet', -- cite map only
['Sheets'] = 'sheets', -- cite map only
['Station'] = 'station',
['SubscriptionRequired'] = 'subscription',
['Time'] = 'time',
['TimeCaption'] = {'time-caption', 'timecaption'},
['Title'] = 'title',
['TitleLink'] = {'title-link', 'episode-link', 'titlelink', 'episodelink'},
['TitleNote'] = 'department',
['TitleType'] = {'type', 'medium'},
['TransChapter'] = {'trans-chapter', 'trans_chapter'},
['TransMap'] = 'trans-map', -- cite map only
['Transcript'] = 'transcript',
['TranscriptFormat'] = 'transcript-format',
['TranscriptURL'] = {'transcript-url', 'transcripturl'},
['TransTitle'] = {'trans-title', 'trans_title', 'title_zh'},
['URL'] = {'url', 'URL'},
['UrlAccess']={'url-access','urlaccess'},
['Vauthors'] = 'vauthors',
['Veditors'] = 'veditors',
['Via'] = 'via',
['Volume'] = 'volume',
['Year'] = 'year',
['AuthorList-First'] = {"first#", "given#", "author-first#", "author#-first"},
['AuthorList-Last'] = {"last#", "author#", "surname#", "author-last#", "author#-last", "subject#"},
['AuthorList-Link'] = {"authorlink#", "author-link#", "author#-link", "subjectlink#", "author#link", "subject-link#", "subject#-link", "subject#link"},
['AuthorList-Mask'] = {"author-mask#", "authormask#", "author#mask", "author#-mask"},
['ContributorList-First'] = {'contributor-first#','contributor#-first'},
['ContributorList-Last'] = {'contributor#', 'contributor-last#', 'contributor#-last'},
['ContributorList-Link'] = {'contributor-link#', 'contributor#-link'},
['ContributorList-Mask'] = {'contributor-mask#', 'contributor#-mask'},
['EditorList-First'] = {"editor-first#", "editor#-first", "editor-given#", "editor#-given"},
['EditorList-Last'] = {"editor#", "editor-last#", "editor#-last", "editor-surname#", "editor#-surname"},
['EditorList-Link'] = {"editor-link#", "editor#-link", "editorlink#", "editor#link"},
['EditorList-Mask'] = {"editor-mask#", "editor#-mask", "editormask#", "editor#mask"},
['TranslatorList-First'] = {'translator-first#','translator#-first'},
['TranslatorList-Last'] = {'translator#', 'translator-last#', 'translator#-last'},
['TranslatorList-Link'] = {'translator-link#', 'translator#-link'},
['TranslatorList-Mask'] = {'translator-mask#', 'translator#-mask'},
}
--[[--------------------------< D E F A U L T S >--------------------------------------------------------------
Default parameter values
TODO: keep this? Only one default?
]]
local defaults = {
['DeadURL'] = 'yes',
}
--[[--------------------------< A R G S _ S U P P O R T >-----------------------------------------------------
These tables hold cite class values (from the template invocation) and identify those templates that support or require
certain parameters.
]]
local args_support = {
['templates_using_volume'] = {'citation', 'AV media', 'book', 'conference', 'encyclopaedia', 'interview', 'journal', 'magazine', 'map', 'news', 'report', 'techreport', 'thesis'},
['templates_using_issue'] = {'citation', 'conference', 'episode', 'interview', 'journal', 'magazine', 'map', 'news'},
['templates_not_using_page'] = {'AV media', 'episode', 'mailinglist', 'newsgroup', 'podcast', 'serial', 'sign', 'speech'},
['templates_involving_time'] = {'AV media', 'episode', 'speech', 'podcast', 'serial'},
['templates_not_using_chapter'] = {'encyclopaedia', 'web', 'news', 'journal', 'magazine', 'pressrelease','podcast', 'newsgroup', 'mailinglist', 'map', 'conference', 'episode', 'serial', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'},
['templates_not_using_chapter_format'] = {'web', 'news', 'journal', 'magazine', 'pressrelease','podcast', 'newsgroup', 'mailinglist', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'},
['templates_using_contributor'] = {'book', 'citation'}, -- |contributor= and |contribution= only supported in book cites
['templates_requiring_url'] = {'web', 'podcast', 'mailinglist'}
}
--[[--------------------------< K E Y W O R D S >--------------------------------------------------------------
This table holds keywords for those parameters that have defined sets of acceptible keywords.
]]
local keywords = {
['yes_true_y'] = {'yes', 'true', 'y'}, -- ignore-isbn-error, last-author-amp, no-tracking, nopp, registration, subscription
['deadurl'] = {'yes', 'true', 'y', 'dead', 'no', 'live', 'unfit', 'usurped'},
['deadurl-live'] = {'no', 'live'},
['deadurl-unfit'] = {'unfit', 'usurped'},
['mode'] = {'cs1', 'cs2'},
['name-list-format'] = {'vanc', 'amp', '&'},
['contribution'] = {'afterword', 'foreword', 'introduction', 'preface'}, -- generic contribution titles that are rendered unquoted in the 'chapter' position
['date-format'] = {'dmy', 'dmy-all', 'mdy', 'mdy-all', 'ymd', 'ymd-all'},
['id-access'] = {'free'},
['url-access'] = {'free', 'limited', 'subscription', 'registration'},
}
--[[--------------------------< I N V I S I B L E _ C H A R A C T E R S >--------------------------------------
This table holds non-printing or invisible characters indexed either by name or by Unicode group. Values are decimal
representations of UTF-8 codes. The table is organized as a table of tables because the lua pairs keyword returns
table data in an arbitrary order. Here, we want to process the table from top to bottom because the entries at
the top of the table are also found in the ranges specified by the entries at the bottom of the table.
This list contains patterns for templates like {{'}} which isn't an error but transcludes characters that are
invisible. These kinds of patterns must be recognized by the functions that use this list.
Also here is a pattern that recognizes stripmarkers that begin and end with the delete characters. The nowiki
stripmarker is not an error but some others are because the parameter values that include them become part of the
template's metadata before stripmarker replacement.
]]
local invisible_chars = {
{'replacement', '\239\191\189', '替换字符'}, -- U+FFFD, EF BF BD
{'apostrophe', '‍\226\128\138\039\226\128\139', '撇号'}, -- apostrophe template: ‍ hair space ' zero-width space; not an error
{'apostrophe', '\226\128\138\039\226\128\139', '撇号'}, -- apostrophe template: hair space ' zero-width space; (as of 2015-12-11) not an error
{'zero width joiner', '\226\128\141', '零宽连字'}, -- U+200D, E2 80 8D
{'zero width space', '\226\128\139', '零宽空格'}, -- U+200B, E2 80 8B
{'hair space', '\226\128\138', '字间最小间隔'}, -- U+200A, E2 80 8A
{'soft hyphen', '\194\173', '软连字符'}, -- U+00AD, C2 AD
{'horizontal tab', '\009', '水平制表'}, -- U+0009 (HT), 09
{'line feed', '\010', '換行符'}, -- U+0010 (LF), 0A
{'carriage return', '\013', '回车符'}, -- U+0013 (CR), 0D
-- {'nowiki stripmarker', '\127UNIQ%-%-nowiki%-[%a%d]+%-QINU\127'}, -- nowiki stripmarker; not an error
{'stripmarker', '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', 'mediawiki占位符'},
-- stripmarker; may or may not be an error; capture returns the stripmaker type
{'delete', '\127', '删除符'}, -- U+007F (DEL), 7F; must be done after stripmarker test
{'C0 control', '[\000-\008\011\012\014-\031]', 'C0控制符'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D))
{'C1 control', '[\194\128-\194\159]', 'C1控制符'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F
{'Specials', '[\239\191\185-\239\191\191]', '特殊字符'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF
{'Private use area', '[\238\128\128-\239\163\191]', '私用空间'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF
{'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]',
'补充私用空间A'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD
{'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]',
'补充私用空间B'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD
}
--[[--------------------------< E X T R A _ T E X T _ P A T T E R N >--------------------------------------
]]
local extra_text_pattern = {
['edition'] = {
['good'] = {
},
['bad'] = {
'%f[%a][Ee]d%.?$',
'%f[%a][Ee]dition$'
}
},
['page'] = {
['good'] = {
'^P[^%.Pp]' -- ok to begin with uppercase P: P7 (pg 7 of section P) but not p123 (page 123) TODO: add Gg for PG or Pg?
},
['bad'] = {
'^[Pp]?[Pp]%.?[ %d]',
'^[Pp]ages?'
}
}
}
--[[---------------------< S T R I P M A R K E R S >----------------------------
Common pattern definition location for stripmarkers so that we don't have to go
hunting for them if (when) MediaWiki changes their form.
]]
local stripmarkers = {
['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker
['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker()
}
local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]';
--[[--------------------------< M A I N T E N A N C E _ C A T E G O R I E S >----------------------------------
Here we name maintenance categories to be used in maintenance messages.
]]
local maint_cats = {
['ASIN'] = '引文格式1维护:ASIN使用ISBN',
['date_year'] = '引文格式1维护:日期与年',
['disp_auth_ed'] = '引文格式1维护:显示-作者', -- $1 is authors or editors
['embargo'] = '引文格式1维护:PMC封锁过期',
['english'] = 'CS1 maint: English language specified',
['etal'] = '引文格式1维护:显式使用等标签',
['extra_text'] = '引文格式1维护:冗余文本',
['ignore_isbn_err'] = '引文格式1维护:ISBN错误被忽略',
['jfm_format'] = '引文格式1维护:jfm格式',
['mr_format'] = '引文格式1维护:MR格式',
['pmc_format'] = '引文格式1维护:PMC格式',
['unknown_lang'] = '引文格式1维护:未识别语文类型',
['untitled'] = '引文格式1维护:无标题期刊',
['zbl_format'] = '引文格式1维护:zbl格式',
['registration'] = '含有內容需登入查看的頁面',
['subscription'] = '含有連結內容需訂閱查看的頁面'
}
--[[--------------------------< P R O P E R T I E S _ C A T E G O R I E S >------------------------------------
Here we name properties categories
]]
local prop_cats = {
['foreign_lang_source'] = 'CS1$1来源 ($2)', -- |language= categories; $1 is language name, $2 is ISO639-1 code
['script'] = 'CS1含有外文文本', -- when language specified by |script-title=xx: doesn't have its own category
['script_with_name'] = 'CS1含有$1文本 ($2)', -- |script-title=xx: has matching category; $1 is language name, $2 is ISO639-1 code
}
--[[--------------------------< T I T L E _ T Y P E S >--------------------------------------------------------
Here we map a template's CitationClass to TitleType (default values for |type= parameter)
]]
local title_types = {
['AV media notes'] = '音像媒体说明',
['interview'] = '访谈',
['mailinglist'] = '邮件列表',
['map'] = '地图',
['podcast'] = '-{zh-cn:播客; zh-tw:Podcast;}-',
['pressrelease'] = '新闻稿',
['report'] = '报告',
['speech'] = '演讲',
['techreport'] = '技术报告',
['thesis'] = '学位论文'
}
--[[--------------------------< E R R O R _ C O N D I T I O N S >----------------------------------------------
Error condition table
The following contains a list of IDs for various error conditions defined in the code. For each ID, we specify a
text message to display, an error category to include, and whether the error message should be wrapped as a hidden comment.
Anchor changes require identical changes to matching anchor in Help:CS1 errors
]]
local error_conditions = {
accessdate_missing_url = {
message = '使用<code style="'..code_style..'">|accessdate=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'accessdate_missing_url',
category = '含有访问日期但无网址的引用的页面',
hidden = true },
archive_missing_date = {
message = '使用<code style="'..code_style..'">|archiveurl=</code>需要含有<code style="'..code_style..'">|archivedate=</code>',
anchor = 'archive_missing_date',
category = '含有存档网址错误的引用的页面',
hidden = false },
archive_missing_url = {
message = '使用<code style="'..code_style..'">|archiveurl=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'archive_missing_url',
category = '含有存档网址错误的引用的页面',
hidden = false },
arxiv_missing = {
message = '需要使用<code style="'..code_style..'">|arxiv=</code>',
anchor = 'arxiv_missing',
category = '引文格式1错误:arXiv', -- same as bad arxiv
hidden = false },
arxiv_params_not_supported = {
message = 'cite arXiv模板填写了不支持的参数',
anchor = 'arxiv_params_not_supported',
category = '引文格式1错误:arXiv', -- same as bad arxiv
hidden = false },
bad_arxiv = {
message = '请检查<code style="'..code_style..'">|arxiv=</code>值',
anchor = 'bad_arxiv',
category = '引文格式1错误:arXiv',
hidden = false },
bad_asin = {
message = '请检查<code style="'..code_style..'">|asin=</code>值',
anchor = 'bad_asin',
category ='引文格式1错误:ASIN',
hidden = false },
bad_bibcode = {
message = '请检查<code style="'..code_style..'">|bibcode=</code>值',
anchor = 'bad_bibcode',
category = '引文格式1错误:bibcode',
hidden = false },
bad_biorxiv = {
message = '请检查<code style="'..code_style..'">|biorxiv=</code>值',
anchor = 'bad_biorxiv',
category = '引文格式1错误:bioRxiv',
hidden = false },
bad_citeseerx = {
message = '请检查<code style="'..code_style..'">|citeseerx=</code>的值',
anchor = 'bad_citeseerx',
category = '引文格式1错误:citeseerx',
hidden = false },
bad_cnid = {
message = '请检查<code style="'..code_style..'">|cn=</code>的值',
anchor = 'bad_cnid',
category = '引文格式1错误:CN',
hidden = false },
bad_date = {
message = '请检查<code style="'..code_style..'">$1</code>中的日期值',
anchor = 'bad_date',
category = '引文格式1错误:日期',
hidden = true },
bad_doi = {
message = '请检查<code style="'..code_style..'">|doi=</code>值',
anchor = 'bad_doi',
category = '引文格式1错误:DOI',
hidden = false },
bad_hdl = {
message = '请检查<code style="'..code_style..'">|hdl=</code>值',
anchor = 'bad_hdl',
category = '引文格式1错误:HDL',
hidden = false },
bad_isbn = {
message = '请检查<code style="'..code_style..'">|isbn=</code>值',
anchor = 'bad_isbn',
category = '含有ISBN错误的引用的页面',
hidden = false },
bad_ismn = {
message = '请检查<code style="'..code_style..'">|ismn=</code>值',
anchor = 'bad_ismn',
category = '引文格式1错误:ISMN',
hidden = false },
bad_issn = {
message = '请检查<code style="'..code_style..'">|issn=</code>值',
anchor = 'bad_issn',
category = '引文格式1错误:ISSN',
hidden = false },
bad_jfm = {
message = '请检查<code style="'..code_style..'">|jfm=</code>值',
anchor = 'bad_jfm',
category = '引文格式1错误:JFM',
hidden = false },
bad_lccn = {
message = '请检查<code style="'..code_style..'">|lccn=</code>值',
anchor = 'bad_lccn',
category = '引文格式1错误:LCCN',
hidden = false },
bad_message_id = {
message = '请检查<code style="'..code_style..'">|message-id=</code>值',
anchor = 'bad_message_id',
category = '引文格式1错误:message-id',
hidden = false },
bad_mr = {
message = '请检查<code style="'..code_style..'">|mr=</code>值',
anchor = 'bad_mr',
category = '引文格式1错误:MR',
hidden = false },
bad_oclc = {
message = '请检查<code style="'..code_style..'">|oclc=</code>值',
anchor = 'bad_oclc',
category = '引文格式1错误:OCLC',
hidden = false },
bad_ol = {
message = '请检查<code style="'..code_style..'">|ol=</code>值',
anchor = 'bad_ol',
category = '引文格式1错误:OL',
hidden = false },
bad_paramlink = { -- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link=
message = '请检查<code style="'..code_style..'">|$1=</code>值',
anchor = 'bad_paramlink',
category = '引文格式1错误:参数链接',
hidden = false },
bad_pmc = {
message = '请检查<code style="'..code_style..'">|pmc=</code>值',
anchor = 'bad_pmc',
category = '引文格式1错误:PMC',
hidden = false },
bad_pmid = {
message = '请检查<code style="'..code_style..'">|pmid=</code>值',
anchor = 'bad_pmid',
category = '引文格式1错误:PMID',
hidden = false },
bad_s2cid = {
message = '请检查<code style="'..code_style..'">|s2cid=</code>的值',
anchor = 'bad_s2cid',
category = '引文格式1错误:S2CID',
hidden = false },
bad_ssrn = {
message = '请检查<code style="'..code_style..'">|ssrn=</code>的值',
anchor = 'bad_ssrn',
category = '引文格式1错误:SSRN',
hidden = false },
bad_url = {
message = '请检查<code style="'..code_style..'">|$1=</code>值',
anchor = 'bad_url',
category = '含有网址格式错误的引用的页面',
hidden = false },
bare_url_missing_title = {
message = '<code style="'..code_style..'">|$1=</code>缺少标题',
anchor = 'bare_url_missing_title',
category = '含有裸露网址的引用的页面',
hidden = false },
bad_zbl = {
message = '请检查<code style="'..code_style..'">|zbl=</code>的值',
anchor = 'bad_zbl',
category = '引文格式1错误:ZBL',
hidden = false },
bad_csbn = {
message = '请检查<code style="'..code_style..'">|csbn=</code>或<code style="'..code_style..'">|unified=</code>的值',
anchor = 'bad_csbn',
category = '引文格式1错误:CSBN',
hidden = false },
class_ignored = {
message = '<code style="'..code_style..'">|class=</code>被忽略',
anchor = 'class_ignored',
category = '引文格式1错误:class参数被忽略',
hidden = false },
chapter_ignored = {
message = '<code style="'..code_style..'">|$1=</code>被忽略',
anchor = 'chapter_ignored',
category = '引文格式1错误:章节参数被忽略',
hidden = false },
citation_missing_title = {
message = '缺少或<code style="'..code_style..'">|title=</code>为空',
anchor = 'citation_missing_title',
category = '含有缺少标题的引用的页面',
hidden = false },
cite_web_url = {
-- this error applies to cite web and to cite podcast
message = '缺少或<code style="'..code_style..'">|url=</code>为空',
anchor = 'cite_web_url',
category = '含有缺少网址的网站引用的页面',
hidden = true },
coauthors_missing_author = {
message = '使用<code style="'..code_style..'">|coauthors=</code>需要含有<code style="'..code_style..'">|author=</code>',
anchor = 'coauthors_missing_author',
category = '引文格式1错误:无主作者的合作者',
hidden = false },
contributor_ignored = {
message = '<code style="'..code_style..'">|contributor=</code>被忽略</code>',
anchor = 'contributor_ignored',
category = '引文格式1错误:合作者',
hidden = false },
contributor_missing_required_param = {
message = '使用<code style="'..code_style..'">|contributor=</code>需要含有<code style="'..code_style..'">|$1=</code>',
anchor = 'contributor_missing_required_param',
category = '引文格式1错误:合作者',
hidden = false },
date_year_mismatch = {
message = '<code style="'..code_style..'">|year=</code>与<code style="'..code_style..'">|$1=</code>不匹配',
anchor = 'date_year_mismatch',
category = '引文格式1错误:日期与年不匹配',
hidden = false },
deprecated_params = {
message = '引文使用过时参数<code style="'..code_style..'">$1</code>',
anchor = 'deprecated_params',
category = '含有过时参数的引用的页面',
hidden = true },
doi_inactive_dated = {
message = '自$1年含有不活躍DOI的頁面',
anchor = 'doi_inactive_dated',
category = '自$1年含有不活躍DOI的頁面',
hidden = true},
doi_inactive = {
message = '含有不活躍DOI的頁面',
anchor = 'doi_inactive_dated',
category = '含有不活躍DOI的頁面',
hidden = true},
empty_citation = {
message = '空引用',
anchor = 'empty_citation',
category = '含有空引用的页面',
hidden = false },
first_missing_last = {
message = '$1列表中的<code style="'..code_style..'">|first$2=</code>缺少<code style="'..code_style..'">|last$2=</code>',
anchor = 'first_missing_last',
category = '引文格式1错误:缺少作者或编者',
hidden = false },
format_missing_url = {
message = '使用<code style="'..code_style..'">|format=</code>需要含有<code style="'..code_style..'">|url=</code>',
anchor = 'format_missing_url',
category = '含有格式却不含网址的引用的页面',
hidden = true },
implict_etal_editor = {
message = '建议使用<code style="'..code_style..'">|displayeditors=</code>',
anchor = 'displayeditors',
category = '含有旧式缩略标签的引用的页面 in editors',
hidden = true },
invalid_param_val = {
message = '无效<code style="'..code_style..'">|$1=$2</code>',
anchor = 'invalid_param_val',
category = '引文格式1错误:无效参数值',
hidden = false },
invisible_char = {
message = '参数$2值左起第$3位存在$1',
anchor = 'invisible_char',
category = '引文格式1错误:不可见字符',
hidden = false },
missing_name = {
message = '$1列表缺少<code style="'..code_style..'">|last$2=</code>',
anchor = 'missing_name',
category = '引文格式1错误:缺少作者或编者',
hidden = false },
param_access_requires_param = {
message = '使用<code style="'..code_style..'">|$1-access=</code>需要含有<code style="'..code_style..'">|$1=</code>',
anchor = 'param_access_requires_param',
category = '含有-access参数但无主参数的引用的页面',
hidden = true },
param_has_ext_link = {
message = '外部链接存在于<code style="'..code_style..'">$1</code>',
anchor = 'param_has_ext_link',
category = '引文格式1错误:外部链接',
hidden = false },
parameter_discarded = {
message = '<code style="'..code_style..'">|$1=</code>被忽略',
anchor = 'parameter_discarded',
category = '引文格式1错误:已知参数被忽略',
hidden = false },
parameter_ignored = {
message = '已忽略未知参数<code style="'..code_style..'">|$1=</code>',
anchor = 'parameter_ignored',
category = '含有未知参数的引用的页面',
hidden = false },
parameter_ignored_suggest = {
message = '已忽略未知参数<code style="'..code_style..'">|$1=</code>(建议使用<code style="'..code_style..'">|$2=</code>)',
anchor = 'parameter_ignored_suggest',
category = '含有未知参数的引用的页面',
hidden = false },
periodical = {
message = '参数<code style="'..code_style..'">|$1=</code>与模板<code style="'..code_style..'">{{cite $2}}</code>不匹配(建议改用<code style="'..code_style..'">{{cite $3}}</code>或<code style="'..code_style..'">|$4=</code>)',
anchor = 'periodical',
category = '引文格式1错误:periodical系列参数与模板类型不匹配',
hidden = false },
redundant_parameters = {
message = '$1只需其一',
anchor = 'redundant_parameters',
category = '含有冗余参数的引用的页面',
hidden = false },
text_ignored = {
message = '已忽略文本“$1”',
anchor = 'text_ignored',
category = '含有未命名参数的引用的页面',
hidden = false },
trans_missing_title = {
message = '使用<code style="'..code_style..'">|trans-title=</code>需要含有<code style="'..code_style..'">|title=</code>',
anchor = 'trans_missing_title',
category = '引文格式1错误:翻译标题',
hidden = false },
vancouver = {
message = '温哥华格式错误',
anchor = 'vancouver',
category = '引文格式1错误:温哥华格式',
hidden = false },
wikilink_in_url = {
message = '网址-维基内链冲突',
anchor = 'wikilink_in_url',
category = '引文格式1错误:网址-维基内链冲突',
hidden = false },
}
--[[--------------------------< I D _ H A N D L E R S >--------------------------------------------------------
The following contains a list of values for various defined identifiers. For each identifier we specify a
variety of information necessary to properly render the identifier in the citation.
parameters: a list of parameter aliases for this identifier
link: Wikipedia article name
label: the alternate name to apply to link
mode: 'manual' when there is a specific function in the code to handle the identifier;
'external' for identifiers that link outside of Wikipedia;
prefix: the first part of a url that will be concatenated with a second part which usually contains the identifier
encode: true if uri should be percent encoded; otherwise false
COinS: identifier link or keyword for use in COinS:
for identifiers registered at info-uri.info use: info:....
for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn
for others make a url using the value in prefix, use the keyword: pre (not checked; any text other than 'info' or 'rft' works here)
set to nil to leave the identifier out of the COinS
separator: character or text between label and the identifier in the rendered citation
]]
local id_handlers = {
['ARXIV'] = {
parameters = {'arxiv', 'ARXIV', 'eprint'},
link = 'arXiv',
label = 'arXiv',
mode = 'manual',
prefix = '//arxiv.org/abs/', -- protocol relative tested 2013-09-04
encode = false,
COinS = 'info:arxiv',
separator = ':',
access = 'free',
},
['ASIN'] = {
parameters = { 'asin', 'ASIN' },
link = '亚马逊标准识别码',
label = 'ASIN',
mode = 'manual',
prefix = '//www.amazon.',
COinS = nil, -- no COinS for this id (needs thinking on implementation because |asin-tld=)
separator = ' ',
encode = false;
},
['BIBCODE'] = {
parameters = {'bibcode', 'BIBCODE'},
link = 'Bibcode',
label = 'Bibcode',
mode = 'manual',
prefix = 'https://ui.adsabs.harvard.edu/abs/',
encode = false,
COinS = 'info:bibcode',
custom_access = 'bibcode-access',
separator = ':',
},
['BIORXIV'] = {
parameters = {'biorxiv'},
link = 'bioRxiv',
label = 'bioRxiv',
mode = 'manual',
prefix = '//doi.org/',
encode = true,
COinS = 'pre',
separator = ' ',
access = 'free',
},
['CITESEERX'] = {
parameters = {'citeseerx'},
link = 'CiteSeerX',
q = 'Q2715061',
label = 'CiteSeerX',
mode = 'manual',
prefix = '//citeseerx.ist.psu.edu/viewdoc/summary?doi=',
COinS = 'pre', -- use prefix value
access = 'free', -- free to read
encode = true,
separator = ' ',
},
['CNID'] = {
parameters = {'cn', 'CN'},
link = '国内统一刊号',
label = "CN",
mode = 'manual',
prefix = 'http://www.nppa.gov.cn/nppa/publishing/view.shtml?&pubCode=',
encode = true,
separator = ' ',
},
['DOI'] = {
parameters = { 'doi', 'DOI' },
link = '數位物件識別號',
q = 'Q25670',
label = 'doi',
mode = 'manual',
prefix = '//doi.org/',
COinS = 'info:doi',
custom_access = 'doi-access',
separator = ':',
encode = true,
},
['EISSN'] = {
parameters = {'eissn', 'EISSN'},
link = 'International_Standard_Serial_Number#Electronic_ISSN',
label = 'eISSN',
mode = 'manual',
prefix = '//www.worldcat.org/issn/',
COinS = 'rft.eissn',
encode = false,
separator = ' ',
},
['HDL'] = {
parameters = { 'hdl', 'HDL' },
link = 'Handle System',
q = 'Q3126718',
label = 'hdl',
mode = 'manual',
prefix = '//hdl.handle.net/',
COinS = 'info:hdl',
custom_access = 'hdl-access',
separator = ':',
encode = true,
},
['ISBN'] = {
parameters = {'isbn', 'ISBN', 'isbn13', 'ISBN13'},
link = '国际标准书号',
label = 'ISBN',
mode = 'manual',
prefix = 'Special:BookSources/',
COinS = 'rft.isbn',
separator = ' ',
},
['ISMN'] = {
parameters = {'ismn', 'ISMN'},
link = 'International Standard Music Number',
label = 'ISMN',
mode = 'manual',
prefix = '', -- not currently used;
COinS = 'nil', -- nil because we can't use pre or rft or info:
separator = ' ',
},
['ISSN'] = {
parameters = {'issn', 'ISSN'},
link = '国际标准连续出版物号',
label = 'ISSN',
mode = 'manual',
prefix = '//www.worldcat.org/issn/',
COinS = 'rft.issn',
encode = false,
separator = ' ',
},
['JFM'] = {
parameters = {'jfm', 'JFM'},
link = 'Jahrbuch über die Fortschritte der Mathematik',
label = 'JFM',
mode = 'manual',
prefix = '//zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['JSTOR'] = {
parameters = {'jstor', 'JSTOR'},
link = 'JSTOR',
label = 'JSTOR',
mode = 'external',
prefix = '//www.jstor.org/stable/', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
custom_access = 'jstor-access',
encode = false,
separator = ' ',
},
['LCCN'] = {
parameters = {'LCCN', 'lccn'},
link = '美国国会图书馆控制码',
label = 'LCCN',
mode = 'manual',
prefix = 'http://lccn.loc.gov/',
COinS = 'info:lccn', -- use prefix value
encode = false,
separator = ' ',
},
['MR'] = {
parameters = {'MR', 'mr'},
link = '數學評論',
label = 'MR',
mode = 'manual',
prefix = '//www.ams.org/mathscinet-getitem?mr=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
['OCLC'] = {
parameters = {'OCLC', 'oclc'},
link = 'OCLC',
label = 'OCLC',
mode = 'manual',
prefix = '//www.worldcat.org/oclc/',
COinS = 'info:oclcnum',
encode = true,
separator = ' ',
},
['OL'] = {
parameters = { 'ol', 'OL' },
link = '开放图书馆',
label = 'OL',
mode = 'manual',
prefix = '//openlibrary.org/',
COinS = nil, -- no COinS for this id (needs thinking on implementation because /authors/books/works/OL)
custom_access = 'ol-access',
separator = ' ',
endode = true,
},
['OSTI'] = {
parameters = {'OSTI', 'osti'},
link = '科学和技术信息办公室',
label = 'OSTI',
mode = 'external',
prefix = '//www.osti.gov/energycitations/product.biblio.jsp?osti_id=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
custom_access = 'osti-access',
encode = true,
separator = ' ',
},
['PMC'] = {
parameters = {'PMC', 'pmc'},
link = '公共医学中心',
label = 'PMC',
mode = 'manual',
prefix = '//www.ncbi.nlm.nih.gov/pmc/articles/PMC',
suffix = " ",
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
access = 'free',
},
['PMID'] = {
parameters = {'PMID', 'pmid'},
link = '公共医学识别码',
label = 'PMID',
mode = 'manual',
prefix = '//www.ncbi.nlm.nih.gov/pubmed/',
COinS = 'info:pmid',
encode = false,
separator = ' ',
},
['RFC'] = {
parameters = {'RFC', 'rfc'},
link = '徵求修正意見書',
label = 'RFC',
mode = 'external',
prefix = '//tools.ietf.org/html/rfc',
COinS = 'pre', -- use prefix value
encode = false,
separator = ' ',
access = 'free',
},
['S2CID'] = {
parameters = {'s2cid', 'S2CID'},
link = 'Semantic Scholar', -- l10n: Not created yet
label = 'S2CID',
mode = 'manual',
prefix = 'https://api.semanticscholar.org/CorpusID:',
COinS = 'pre', -- use prefix value
custom_access = 's2cid-access',
encode = false,
separator = ' ',
},
['SSRN'] = {
parameters = {'SSRN', 'ssrn'},
link = '社会科学研究网络',
label = 'SSRN',
mode = 'manual',
prefix = '//ssrn.com/abstract=', -- protocol relative tested 2013-09-04
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
access = 'free',
},
['USENETID'] = {
parameters = {'message-id'},
link = 'Usenet',
label = 'Usenet:',
mode = 'manual',
prefix = 'news:',
encode = false,
COinS = 'pre', -- use prefix value
separator = ' ',
},
['ZBL'] = {
parameters = {'ZBL', 'zbl'},
link = 'Zentralblatt MATH',
label = 'Zbl',
mode = 'manual',
prefix = '//zbmath.org/?format=complete&q=an:',
COinS = 'pre', -- use prefix value
encode = true,
separator = ' ',
},
-- LOCAL
['CSBN'] = {
parameters = {'unified', 'csbn', 'CSBN'},
link = '统一书号',
label = 'CSBN',
mode = 'manual',
prefix = 'http://book.douban.com/subject_search?search_text=SH',
COinS = 'rft.csbn',
encode = true,
separator = ' ',
},
-- END LOCAL
}
return {
aliases = aliases,
args_support = args_support,
defaults = defaults,
error_conditions = error_conditions,
indic_script = indic_script,
internal_errors = internal_errors,
id_handlers = id_handlers,
keywords = keywords,
invisible_chars = invisible_chars,
extra_text_pattern = extra_text_pattern,
maint_cats = maint_cats,
messages = messages,
periodical = periodical,
presentation = presentation,
prop_cats = prop_cats,
stripmarkers = stripmarkers,
title_types = title_types,
uncategorized_namespaces = uncategorized_namespaces,
uncategorized_subpages = uncategorized_subpages,
}
d3306a3bbc1c9c3932fd2acd56c3ed70f5b08e8e
Module:Citation/CS1/Whitelist
828
177
361
360
2024-08-04T12:21:57Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< P A R A M E T E R S N O T S U P P O R T E D >------------------------------
This is a list of parameters that once were but now are no longer supported:
['albumlink'] = nil, -- unique alias of titlelink used by old cite AV media notes
['albumtype'] = nil, -- controled inappropriate functionality in the old cite AV media notes
['artist'] = nil, -- unique alias of others used by old cite AV media notes
['Author'] = nil, -- non-standard capitalization
['authorformat'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['author-format'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['author-name-separator'] = nil,-- primarily used to support Vancouver format which functionality now part of name-list-format
['author-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['began'] = nil, -- module handles date ranges; cite episode and cite series
['chapterlink'] = nil, -- if ever necessary to link to a chapter article, |chapter= can be wikilinked
['chapter-link'] = nil, --
['cointerviewers'] = nil, -- unique alias of others used by old cite interview
['day'] = nil, -- deprecated in {{citation/core}} and somehow undeprecated in Module:Citation/CS1 and now finally removed
['director'] = nil, -- unique alias of author used by old cite DVD-notes
['DoiBroken'] = nil, -- not used, non-standard captialization
['Editor'] = nil, -- non-standard capitalization
['editorformat'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['EditorSurname'] = nil, -- non-standard capitalization
['editor-format'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['EditorGiven'] = nil, -- non-standard capitalization
['editor-name-separator'] = nil,-- primarily used to support Vancouver format which functionality now part of name-list-format
['editor-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['Embargo'] = nil, -- not used, non-standard capitalization
['ended'] = nil, -- module handles date ranges; cite episode and cite series
['month'] = nil, -- functionality supported by |date=
['name-separator'] = nil, -- primarily used to support Vancouver format which functionality now part of name-list-format
['notestitle'] = nil, -- unique alias of chapter used by old cite AV media notes
['PPrefix'] = nil, -- non-standard capitalization
['PPPrefix'] = nil, -- not used, non-standard capitalization
['pp-prefix'] = nil, -- not used, not documented
['p-prefix'] = nil, -- not used, not documented
['publisherid'] = nil, -- unique alias of id used by old cite AV media notes and old cite DVD-notes
['Ref'] = nil, -- non-statndard capitalization
['separator'] = nil, -- this functionality now provided by |mode=
['titleyear'] = nil, -- unique alias of origyear used by old cite DVD-notes
['Author#'] = nil, -- non-standard capitalization
['authors#'] = nil, -- no need for multiple lists of author names
['Editor#'] = nil, -- non-standard capitalization
['editors#'] = nil, -- no need for multiple lists of editor names
['EditorGiven#'] = nil, -- non-standard capitalization
['EditorSurname#'] = nil, -- non-standard capitalization
]]
--[[--------------------------< S U P P O R T E D P A R A M E T E R S >--------------------------------------
Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values:
true - these parameters are valid and supported parameters
false - these parameters are deprecated but still supported
nil - these parameters are no longer supported (when setting a parameter to nil, leave a comment stating the reasons for invalidating the parameter)
]]
local whitelist = {}
local basic_arguments = {
['accessdate'] = true,
['access-date'] = true,
['agency'] = true,
['airdate'] = true,
['air-date'] = true,
['archivedate'] = true,
['archive-date'] = true,
['archive-format'] = true,
['archiveurl'] = true,
['archive-url'] = true,
['article'] = true,
['arxiv'] = true,
['ARXIV'] = true,
['asin'] = true,
['ASIN'] = true,
['asin-tld'] = true,
['ASIN-TLD'] = true,
['at'] = true,
['author'] = true,
['author-first'] = true,
['author-last'] = true,
['authorlink'] = true,
['author-link'] = true,
['authormask'] = true,
['author-mask'] = true,
['authors'] = true,
['bibcode'] = true,
['BIBCODE'] = true,
['bibcode-access'] = true,
['biorxiv'] = true,
['booktitle'] = true,
['book-title'] = true,
['callsign'] = true, -- cite interview
['call-sign'] = true, -- cite interview
['cartography'] = true,
['chapter'] = true,
['chapter-format'] = true,
['chapterurl'] = true,
['chapter-url'] = true,
['chapter-url-access'] = true,
['citeseerx'] = true,
['city'] = true, -- cite interview, cite episode, cite serial
['class'] = true, -- cite arxiv and arxiv identifiers
['cn'] = true,
['CN'] = true,
['coauthor'] = false, -- deprecated
['coauthors'] = false, -- deprecated
['conference'] = true,
['conference-format'] = true,
['conferenceurl'] = true,
['conference-url'] = true,
['contribution'] = true,
['contribution-format'] = true,
['contributionurl'] = true,
['contribution-url'] = true,
['contributor'] = true,
['contributor-first'] = true,
['contributor-last'] = true,
['contributor-link'] = true,
['contributor-mask'] = true,
['credits'] = true, -- cite episode, cite serial
['date'] = true,
['deadurl'] = true,
['dead-url'] = true,
['degree'] = true,
['department'] = true,
['dictionary'] = true,
['displayauthors'] = true,
['display-authors'] = true,
['displayeditors'] = true,
['display-editors'] = true,
['docket'] = true,
['doi'] = true,
['DOI'] = true,
['doi-access'] = true,
['doi-broken'] = true,
['doi_brokendate'] = true,
['doi-broken-date'] = true,
['doi_inactivedate'] = true,
['doi-inactive-date'] = true,
['edition'] = true,
['editor'] = true,
['editor-first'] = true,
['editor-given'] = true,
['editor-last'] = true,
['editorlink'] = true,
['editor-link'] = true,
['editormask'] = true,
['editor-mask'] = true,
['editors'] = true,
['editor-surname'] = true,
['eissn'] = true,
['EISSN'] = true,
['embargo'] = true,
['encyclopaedia'] = true,
['encyclopedia'] = true,
['entry'] = true,
['episode'] = true, -- cite serial only TODO: make available to cite episode?
['episodelink'] = true, -- cite episode and cite serial
['episode-link'] = true, -- cite episode and cite serial
['eprint'] = true, -- cite arxiv and arxiv identifiers
['event'] = true,
['event-format'] = true,
['eventurl'] = true,
['event-url'] = true,
['first'] = true,
['format'] = true,
['given'] = true,
['hdl'] = true,
['HDL'] = true,
['hdl-access'] = true,
['host'] = true,
['id'] = true,
['ID'] = true,
['ignoreisbnerror'] = true,
['ignore-isbn-error'] = true,
['in'] = true,
['inset'] = true,
['institution'] = true,
['interviewer'] = true, --cite interview
['interviewers'] = true, --cite interview
['isbn'] = true,
['ISBN'] = true,
['isbn13'] = true,
['ISBN13'] = true,
['ismn'] = true,
['ISMN'] = true,
['issn'] = true,
['ISSN'] = true,
['issue'] = true,
['jfm'] = true,
['JFM'] = true,
['journal'] = true,
['jstor'] = true,
['JSTOR'] = true,
['jstor-access'] = true,
['language'] = true,
['last'] = true,
['lastauthoramp'] = true,
['last-author-amp'] = true,
['laydate'] = true,
['lay-date'] = true,
['laysource'] = true,
['lay-source'] = true,
['laysummary'] = true,
['lay-summary'] = true,
['lay-format'] = true,
['layurl'] = true,
['lay-url'] = true,
['lccn'] = true,
['LCCN'] = true,
['location'] = true,
['magazine'] = true,
['mailinglist'] = true, -- cite mailing list only
['mailing-list'] = true, -- cite mailing list only
['map'] = true, -- cite map only
['map-format'] = true, -- cite map only
['mapurl'] = true, -- cite map only
['map-url'] = true, -- cite map only
['map-url-access'] = true, -- cite map only
['medium'] = true,
['message-id'] = true, -- cite newsgroup
['minutes'] = true,
['mode'] = true,
['mr'] = true,
['MR'] = true,
['name-list-format'] = true,
['name-list-style'] = true,
['network'] = true,
['newsgroup'] = true,
['newspaper'] = true,
['nocat'] = true,
['no-cat'] = true,
['nopp'] = true,
['no-pp'] = true,
['notracking'] = true,
['no-tracking'] = true,
['number'] = true,
['oclc'] = true,
['OCLC'] = true,
['ol'] = true,
['OL'] = true,
['ol-access'] = true,
['origyear'] = true,
['orig-year'] = true,
['osti'] = true,
['OSTI'] = true,
['osti-access'] = true,
['others'] = true,
['p'] = true,
['page'] = true,
['pages'] = true,
['people'] = true,
['periodical'] = true,
['place'] = true,
['pmc'] = true,
['PMC'] = true,
['pmid'] = true,
['PMID'] = true,
['postscript'] = true,
['pp'] = true,
['program'] = true, -- cite interview
['publicationdate'] = true,
['publication-date'] = true,
['publicationplace'] = true,
['publication-place'] = true,
['publisher'] = true,
['quotation'] = true,
['quote'] = true,
['ref'] = true,
['registration'] = true,
['rfc'] = true,
['RFC'] = true,
['s2cid'] = true,
['s2cid-access'] = true,
['scale'] = true,
['script-chapter'] = true,
['script-title'] = true,
['season'] = true,
['section'] = true,
['section-format'] = true,
['sections'] = true, -- cite map only
['sectionurl'] = true,
['section-url'] = true,
['section-url-access'] = true,
['series'] = true,
['serieslink'] = true,
['series-link'] = true,
['seriesno'] = true,
['series-no'] = true,
['seriesnumber'] = true,
['series-number'] = true,
['series-separator'] = true,
['sheet'] = true, -- cite map only
['sheets'] = true, -- cite map only
['ssrn'] = true,
['SSRN'] = true,
['station'] = true,
['subject'] = true,
['subjectlink'] = true,
['subject-link'] = true,
['subscription'] = true,
['surname'] = true,
['template doc demo'] = true,
['template-doc-demo'] = true,
['time'] = true,
['timecaption'] = true,
['time-caption'] = true,
['title'] = true,
['titlelink'] = true,
['title-link'] = true,
['title_zh'] = true,
['trans_chapter'] = true,
['trans-chapter'] = true,
['trans-map'] = true,
['transcript'] = true,
['transcript-format'] = true,
['transcripturl'] = true,
['transcript-url'] = true,
['trans_title'] = true,
['trans-title'] = true,
['translator'] = true,
['translator-first'] = true,
['translator-last'] = true,
['translator-link'] = true,
['translator-mask'] = true,
['type'] = true,
['url'] = true,
['URL'] = true,
['urlaccess'] = true,
['url-access'] = true,
['urlstatus'] = true,
['url-status'] = true,
['vauthors'] = true,
['veditors'] = true,
['version'] = true,
['via'] = true,
['volume'] = true,
['website'] = true,
['work'] = true,
['year'] = true,
['zbl'] = true,
['ZBL'] = true,
['unified'] = true,
['csbn'] = true,
['CSBN'] = true,
}
local numbered_arguments = {
['author#'] = true,
['author-first#'] = true,
['author#-first'] = true,
['author-last#'] = true,
['author#-last'] = true,
['author-link#'] = true,
['author#link'] = true,
['author#-link'] = true,
['authorlink#'] = true,
['author-mask#'] = true,
['author#mask'] = true,
['author#-mask'] = true,
['authormask#'] = true,
['contributor#'] = true,
['contributor-first#'] = true,
['contributor#-first'] = true,
['contributor-last#'] = true,
['contributor#-last'] = true,
['contributor-link#'] = true,
['contributor#-link'] = true,
['contributor-mask#'] = true,
['contributor#-mask'] = true,
['editor#'] = true,
['editor-first#'] = true,
['editor#-first'] = true,
['editor#-given'] = true,
['editor-given#'] = true,
['editor-last#'] = true,
['editor#-last'] = true,
['editor-link#'] = true,
['editor#link'] = true,
['editor#-link'] = true,
['editorlink#'] = true,
['editor-mask#'] = true,
['editor#mask'] = true,
['editor#-mask'] = true,
['editormask#'] = true,
['editor#-surname'] = true,
['editor-surname#'] = true,
['first#'] = true,
['given#'] = true,
['last#'] = true,
['subject#'] = true,
['subject-link#'] = true,
['subject#link'] = true,
['subject#-link'] = true,
['subjectlink#'] = true,
['surname#'] = true,
['translator#'] = true,
['translator-first#'] = true,
['translator#-first'] = true,
['translator-last#'] = true,
['translator#-last'] = true,
['translator-link#'] = true,
['translator#-link'] = true,
['translator-mask#'] = true,
['translator#-mask'] = true,
}
return {basic_arguments = basic_arguments, numbered_arguments = numbered_arguments};
17890b7a4dad9667afd0644db8db6c1310f214b0
Module:Citation/CS1/Date validation
828
178
363
362
2024-08-04T12:21:58Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
--[[--------------------------< I S _ V A L I D _ D A T E _ F R O M _ A _ P O I N T >-------------------------
将日期验证的逻辑拆分出来,供其它模块使用
]]
local function is_valid_date_from_a_point (date, point_ts)
local lang = mw.getContentLanguage();
local good1, good2;
local access_ts, tomorrow_ts; -- to hold unix time stamps representing the dates
good1, access_ts = pcall( lang.formatDate, lang, 'U', date ); -- convert date value to unix timesatmp
good2, tomorrow_ts = pcall( lang.formatDate, lang, 'U', 'today + 2 days' ); -- today midnight + 2 days is one second more than all day tomorrow
if good1 and good2 then
access_ts = tonumber (access_ts); -- convert to numbers for the comparison
tomorrow_ts = tonumber (tomorrow_ts);
else
return false; -- one or both failed to convert to unix time stamp
end
if point_ts <= access_ts and access_ts < tomorrow_ts then -- the point <= date < tomorrow's date
return true;
else
return false; -- date out of range
end
end
--[[--------------------------< I S _ V A L I D _ A C C E S S D A T E >----------------------------------------
returns true if:
Wikipedia start date <= accessdate < today + 2 days
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)
accessdate is the date provided in |accessdate= at time 00:00:00 UTC
today is the current date at time 00:00:00 UTC plus 48 hours
if today is 2015-01-01T00:00:00 then
adding 24 hours gives 2015-01-02T00:00:00 – one second more than today
adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow
]]
local function is_valid_accessdate (accessdate)
accessdate = accessdate:gsub("年", "-");
accessdate = accessdate:gsub("月", "-");
accessdate = accessdate:gsub("日", "-");
accessdate = accessdate:gsub("-$", "");
return is_valid_date_from_a_point (accessdate, 979516800);
end
--[[--------------------------< G E T _ M O N T H _ N U M B E R >----------------------------------------------
returns a number according to the month in a date: 1 for January, etc. Capitalization and spelling must be correct. If not a valid month, returns 0
]]
local function get_month_number (month)
local long_months = {['January']=1, ['February']=2, ['March']=3, ['April']=4, ['May']=5, ['June']=6, ['July']=7, ['August']=8, ['September']=9, ['October']=10, ['November']=11, ['December']=12};
local short_months = {['Jan']=1, ['Feb']=2, ['Mar']=3, ['Apr']=4, ['May']=5, ['Jun']=6, ['Jul']=7, ['Aug']=8, ['Sep']=9, ['Oct']=10, ['Nov']=11, ['Dec']=12};
local zh_months = {['1月']=1, ['2月']=2, ['3月']=3, ['4月']=4, ['5月']=5, ['6月']=6, ['7月']=7, ['8月']=8, ['9月']=9, ['10月']=10, ['11月']=11, ['12月']=12}; -- LOCAL
local temp;
temp=long_months[month];
if temp then return temp; end -- if month is the long-form name
temp=short_months[month];
if temp then return temp; end -- if month is the short-form name
temp=zh_months[month]; -- LOCAL
if temp then return temp; end -- if month is in Chinese -- LOCAL
return 0; -- misspelled, improper case, or not a month name
end
--[[--------------------------< G E T _ S E A S O N _ N U M B E R >--------------------------------------------
returns a number according to the sequence of seasons in a year: 1 for Winter, etc. Capitalization and spelling must be correct. If not a valid season, returns 0
]]
local function get_season_number (season)
local season_list = {['Winter']=21, ['Spring']=22, ['Summer']=23, ['Fall']=24, ['Autumn']=24}; -- make sure these numbers do not overlap month numbers
local temp;
temp=season_list[season];
if temp then return temp; end -- if season is a valid name return its number
return 0; -- misspelled, improper case, or not a season name
end
--[[--------------------------< I S _ P R O P E R _ N A M E >--------------------------------------------------
returns a non-zero number if date contains a recognized proper name. Capitalization and spelling must be correct.
]]
local function is_proper_name (name)
local name_list = {['Christmas']=31}
local temp;
temp=name_list[name];
if temp then return temp; end -- if name is a valid name return its number
return 0; -- misspelled, improper case, or not a proper name
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ O R _ S E A S O N >------------------------------
--returns true if month or season is valid (properly spelled, capitalized, abbreviated)
]]
local function is_valid_month_or_season (month_season)
if 0 == get_month_number (month_season) then -- if month text isn't one of the twelve months, might be a season
if 0 == get_season_number (month_season) then -- not a month, is it a season?
return false; -- return false not a month or one of the five seasons
end
end
return true;
end
--[[--------------------------< I S _ V A L I D _ Y E A R >----------------------------------------------------
Function gets current year from the server and compares it to year from a citation parameter. Years more than one year in the future are not acceptable.
]]
local function is_valid_year(year)
if not is_set(year_limit) then
year_limit = tonumber(os.date("%Y"))+1; -- global variable so we only have to fetch it once
end
return tonumber(year) <= year_limit; -- false if year is in the future more than one year
end
--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------
Returns true if day is less than or equal to the number of days in month and year is no farther into the future
than next year; else returns false.
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately
1923) dates are assumed to be Gregorian.
]]
local function is_valid_date (year, month, day)
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
if not is_valid_year(year) then -- no farther into the future than next year
return false;
end
month = tonumber(month); -- required for YYYY-MM-DD dates
if (2==month) then -- if February
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 0==(year%4) then
month_length = 29;
end
else -- Gregorian calendar
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
end
end
else
month_length=days_in_month[month];
end
if tonumber (day) > month_length then
return false;
end
return true;
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E >--------------------------
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August.
There is a special test for May because it can be either short or long form.
Returns true when style for both months is the same
]]
local function is_valid_month_range_style (month1, month2)
local len1 = month1:len();
local len2 = month2:len();
if len1 == len2 then
return true; -- both months are short form so return true
elseif 'May' == month1 or 'May'== month2 then
return true; -- both months are long form so return true
elseif 3 == len1 or 3 == len2 then
return false; -- months are mixed form so return false
else
return true; -- both months are long form so return true
end
end
--[[--------------------------< I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E >------------------------
Check a pair of months or seasons to see if both are valid members of a month or season pair.
Month pairs are expected to be left to right, earliest to latest in time.
Similarly, seasons are also left to right, earliest to latest in time. There is an oddity with seasons: winter is assigned a value of 1, spring 2, ...,
fall and autumn 4. Because winter can follow fall/autumn at the end of a calender year, a special test is made to see if |date=Fall-Winter yyyy (4-1) is the date.
]]
local function is_valid_month_season_range(range_start, range_end)
local range_start_number = get_month_number (range_start);
if 0 == range_start_number then -- is this a month range?
local range_start_number = get_season_number (range_start); -- not a month; is it a season? get start season number
local range_end_number = get_season_number (range_end); -- get end season number
if 0 ~= range_start_number then -- is start of range a season?
if range_start_number < range_end_number then -- range_start is a season
return true; -- return true when range_end is also a season and follows start season; else false
end
if 24 == range_start_number and 21 == range_end_number then -- special case when season range is Fall-Winter or Autumn-Winter
return true;
end
end
return false; -- range_start is not a month or a season; or range_start is a season and range_end is not; or improper season sequence
end
local range_end_number = get_month_number (range_end); -- get end month number
if range_start_number < range_end_number then -- range_start is a month; does range_start precede range_end?
if is_valid_month_range_style (range_start, range_end) then -- do months have the same style?
return true; -- proper order and same style
end
end
return false; -- range_start month number is greater than or equal to range end number; or range end isn't a month
end
--[[--------------------------< M A K E _ C O I N S _ D A T E >------------------------------------------------
This function receives a table of date parts for one or two dates and an empty table reference declared in
Module:Citation/CS1. The function is called only for |date= parameters and only if the |date=<value> is
determined to be a valid date format. The question of what to do with invalid date formats is not answered here.
The date parts in the input table are converted to an ISO 8601 conforming date string:
single whole dates: yyyy-mm-dd
month and year dates: yyyy-mm
year dates: yyyy
ranges: yyyy-mm-dd/yyyy-mm-dd
yyyy-mm/yyyy-mm
yyyy/yyyy
Dates in the Julian calendar are reduced to year or year/year so that we don't have to do calendar conversion from
Julian to Proleptic Gregorian.
The input table has:
year, year2 – always present; if before 1582, ignore months and days if present
month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 31– proper name dates
day, day2 – 0 if not provided, 1-31 for days
the output table receives:
rftdate: an IS8601 formatted date
rftchron: a free-form version of the date, usually without year which is in rftdate (season ranges and propername dates)
rftssn: one of four season keywords: winter, spring, summer, fall (lowercase)
]]
local function make_COinS_date (input, tCOinS_date)
local date; -- one date or first date in a range
local date2 = ''; -- end of range date
if 1582 > tonumber(input.year) or 20 < tonumber(input.month) then -- Julian calendar or season so &rft.date gets year only
date = input.year;
if 0 ~= input.year2 and input.year ~= input.year2 then -- if a range, only the second year portion when not the same as range start year
date = string.format ('%.4d/%.4d', tonumber(input.year), tonumber(input.year2)) -- assemble the date range
end
if 20 < tonumber(input.month) then -- if season or propername date
local season = {[21]='winter', [22]='spring', [23]='summer', [24]='fall', [31]='Christmas'}; -- seasons lowercase, no autumn; proper names use title case
if 0 == input.month2 then -- single season date
if 30 <tonumber(input.month) then
tCOinS_date.rftchron = season[input.month]; -- proper name dates
else
tCOinS_date.rftssn = season[input.month]; -- seasons
end
else -- season range with a second season specified
if input.year ~= input.year2 then -- season year – season year range or season year–year
tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
if 0~= month2 then
tCOinS_date.rftchron = string.format ('%s %s – %s %s', season[input.month], input.year, season[input.month2], input.year2);
end
else -- season–season year range
tCOinS_date.rftssn = season[input.month]; -- start of range season; keep this?
tCOinS_date.rftchron = season[input.month] .. '–' .. season[input.month2]; -- season–season year range
end
end
end
tCOinS_date.rftdate = date;
return; -- done
end
if 0 ~= input.day then
date = string.format ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day)); -- whole date
elseif 0 ~= input.month then
date = string.format ('%s-%.2d', input.year, tonumber(input.month)); -- year and month
else
date = string.format ('%s', input.year); -- just year
end
if 0 ~= input.year2 then
if 0 ~= input.day2 then
date2 = string.format ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2)); -- whole date
elseif 0 ~= input.month2 then
date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2)); -- year and month
else
date2 = string.format ('/%s', input.year2); -- just year
end
end
tCOinS_date.rftdate = date .. date2; -- date2 has the '/' separator
return;
end
--[[--------------------------< C H E C K _ D A T E >----------------------------------------------------------
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only
allowed range separator is endash. Additionally, check the date to see that it is a real date: no 31 in 30-day
months; no 29 February when not a leap year. Months, both long-form and three character abbreviations, and seasons
must be spelled correctly. Future years beyond next year are not allowed.
If the date fails the format tests, this function returns false and does not return values for anchor_year and
COinS_date. When this happens, the date parameter is used in the COinS metadata and the CITEREF identifier gets
its year from the year parameter if present otherwise CITEREF does not get a date value.
Inputs:
date_string - date string from date-holding parameters (date, year, accessdate, embargo, archivedate, etc.)
Returns:
false if date string is not a real date; else
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
COinS_date is ISO 8601 format date; see make_COInS_date()
]]
local function check_date (date_string, tCOinS_date)
local year; -- assume that year2, months, and days are not used;
local year2=0; -- second year in a year range
local month=0;
local month2=0; -- second month in a month range
local day=0;
local day2=0; -- second day in a day range
local anchor_year;
local coins_date;
if date_string:match("^%d%d%d%d%-%d%d%-%d%d$") then -- year-initial numerical year month day format
year, month, day=string.match(date_string, "(%d%d%d%d)%-(%d%d)%-(%d%d)");
if 12 < tonumber(month) or 1 > tonumber(month) or 1583 > tonumber(year) then return false; end -- month number not valid or not Gregorian calendar
anchor_year = year;
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial: month day, year
month, day, anchor_year, year=string.match(date_string, "(%a+)%s*(%d%d?),%s*((%d%d%d%d)%a?)");
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif date_string:match("^%a+ +[1-9]%d?–[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month-initial day range: month day–day, year; days are separated by endash
month, day, day2, anchor_year, year=string.match(date_string, "(%a+) +(%d%d?)–(%d%d?), +((%d%d%d%d)%a?)");
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-initial: day month year
day, month, anchor_year, year=string.match(date_string, "(%d%d*)%s*(%a+)%s*((%d%d%d%d)%a?)");
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
elseif date_string:match("^[1-9]%d?–[1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day-range-initial: day–day month year; days are separated by endash
day, day2, month, anchor_year, year=string.match(date_string, "(%d%d?)–(%d%d?) +(%a+) +((%d%d%d%d)%a?)");
if tonumber(day) >= tonumber(day2) then return false; end -- date range order is left to right: earlier to later; dates may not be the same;
month = get_month_number (month);
if 0 == month then return false; end -- return false if month text isn't one of the twelve months
month2=month; -- for metadata
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ – [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-range: day month - day month year; uses spaced endash
day, month, day2, month2, anchor_year, year=date_string:match("(%d%d?) +(%a+) – (%d%d?) +(%a+) +((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end -- date range order is left to right: earlier to later;
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2=year;
elseif date_string:match("^%a+ +[1-9]%d? – %a+ +[1-9]%d?, +[1-9]%d%d%d?%a?$") then -- month initial month-day-range: month day – month day, year; uses spaced endash
month, day, month2, day2, anchor_year, year=date_string:match("(%a+) +(%d%d?) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
year2=year;
elseif date_string:match("^[1-9]%d? +%a+ +[1-9]%d%d%d – [1-9]%d? +%a+ +[1-9]%d%d%d%a?$") then -- day initial month-day-year-range: day month year - day month year; uses spaced endash
day, month, year, day2, month2, anchor_year, year2=date_string:match("(%d%d?) +(%a+) +(%d%d%d%d?) – (%d%d?) +(%a+) +((%d%d%d%d?)%a?)");
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
elseif date_string:match("^%a+ +[1-9]%d?, +[1-9]%d%d%d – %a+ +[1-9]%d?, +[1-9]%d%d%d%a?$") then -- month initial month-day-year-range: month day, year – month day, year; uses spaced endash
month, day, year, month2, day2, anchor_year, year2=date_string:match("(%a+) +(%d%d?), +(%d%d%d%d) – (%a+) +(%d%d?), +((%d%d%d%d)%a?)");
if tonumber(year2) <= tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end -- year2 no more than one year in the future; months same style
month = get_month_number (month); -- for metadata
month2 = get_month_number (month2);
elseif date_string:match("^%a+ +[1-9]%d%d%d–%d%d%a?$") then -- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash
local century;
month, year, century, anchor_year, year2=date_string:match("(%a+) +((%d%d)%d%d)–((%d%d)%a?)");
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
year2 = century..year2; -- add the century to year2 for comparisons
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number (month);
elseif date_string:match("^%a+ +[1-9]%d%d%d–[1-9]%d%d%d%a?$") then -- special case Winter/Summer year-year; year separated with unspaced endash
month, year, anchor_year, year2=date_string:match("(%a+) +(%d%d%d%d)–((%d%d%d%d)%a?)");
if 'Winter' ~= month and 'Summer' ~= month then return false end; -- 'month' can only be Winter or Summer
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
if 1 ~= tonumber(year2) - tonumber(year) then return false; end -- must be sequential years, left to right, earlier to later
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
month = get_season_number (month); -- for metadata
elseif date_string:match("^%a+ +[1-9]%d%d%d% – %a+ +[1-9]%d%d%d%a?$") then -- month/season year - month/season year; separated by spaced endash
month, year, month2, anchor_year, year2=date_string:match("(%a+) +(%d%d%d%d) – (%a+) +((%d%d%d%d)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor_year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then -- both must be month year, same month style
month = get_month_number(month);
month2 = get_month_number(month2);
elseif 0 ~= get_season_number(month) and 0 ~= get_season_number(month2) then -- both must be or season year, not mixed
month = get_season_number(month);
month2 = get_season_number(month2);
else
return false;
end
elseif date_string:match ("^%a+–%a+ +[1-9]%d%d%d%a?$") then -- month/season range year; months separated by endash
month, month2, anchor_year, year=date_string:match ("(%a+)–(%a+)%s*((%d%d%d%d)%a?)");
if (not is_valid_month_season_range(month, month2)) or (not is_valid_year(year)) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
month2 = get_month_number(month2);
else
month = get_season_number(month);
month2 = get_season_number(month2);
end
year2=year;
elseif date_string:match("^%a+ +%d%d%d%d%a?$") then -- month/season year or proper-name year
month, anchor_year, year=date_string:match("(%a+)%s*((%d%d%d%d)%a?)");
if not is_valid_year(year) then return false; end
if not is_valid_month_or_season (month) and 0 == is_proper_name (month) then return false; end
if 0 ~= get_month_number(month) then -- determined to be a valid range so just check this one to know if month or season
month = get_month_number(month);
elseif 0 ~= get_season_number(month) then
month = get_season_number(month);
else
month = is_proper_name (month); -- must be proper name; not supported in COinS
end
elseif date_string:match("^[1-9]%d%d%d?–[1-9]%d%d%d?%a?$") then -- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999
year, anchor_year, year2=date_string:match("(%d%d%d%d?)–((%d%d%d%d?)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor year from both years
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif date_string:match("^[1-9]%d%d%d–%d%d%a?$") then -- Year range: YYYY–YY; separated by unspaced endash
local century;
year, century, anchor_year, year2=date_string:match("((%d%d)%d%d)–((%d%d)%a?)");
anchor_year=year..'–'..anchor_year; -- assemble anchor year from both years
if 13 > tonumber(year2) then return false; end -- don't allow 2003-05 which might be May 2003
year2 = century..year2; -- add the century to year2 for comparisons
if tonumber(year) >= tonumber(year2) then return false; end -- left to right, earlier to later, not the same
if not is_valid_year(year2) then return false; end -- no year farther in the future than next year
elseif date_string:match("^[1-9]%d%d%d?%a?$") then -- year; here accept either YYY or YYYY
anchor_year, year=date_string:match("((%d%d%d%d?)%a?)");
if false == is_valid_year(year) then
return false;
end
-- LOCAL: do not use mw.ustring: it allows full-width characters for %d.
elseif date_string:match("^[1-9]%d%d%d年[1-9]%d?月[1-9]%d?日$") then -- zh: year month day
year, month, day=date_string:match("(%d%d%d%d)年(%d%d*月)(%d%d*)日");
month = get_month_number (month);
if 0 == month then return false; end
anchor_year = year;
elseif date_string:match("^[1-9]%d%d%d年[1-9]%d?月$") then -- zh: year month
year, month=date_string:match("(%d%d%d%d)年(%d%d*月)");
month = get_month_number (month);
if 0 == month then return false; end
anchor_year = year;
elseif date_string:match("^[1-9]%d%d%d?年$") then -- zh: year; here accept either YYY or YYYY
year=date_string:match("(%d%d%d%d?)年");
if false == is_valid_year(year) then
return false;
end
anchor_year = year;
elseif date_string:match("^%d%d%d%d%-%d%d$") then -- numerical year month format
year, month=date_string:match("(%d%d%d%d)%-(%d%d)");
month=tonumber(month);
if 12 < month or 1 > month or 1583 > tonumber(year) then return false; end -- month number not valid or not Gregorian calendar
anchor_year = year;
-- END LOCAL
else
return false; -- date format not one of the MOS:DATE approved formats
end
local result=true; -- check whole dates for validity; assume true because not all dates will go through this test
if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then -- YMD (simple whole date)
result=is_valid_date(year,month,day);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then -- YMD-d (day range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year,month,day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-md (day month range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year,month2,day2);
elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then -- YMD-ymd (day month year range)
result=is_valid_date(year,month,day);
result=result and is_valid_date(year2,month2,day2);
end
if false == result then return false; end
if nil ~= tCOinS_date then -- this table only passed into this function when testing |date= parameter values
make_COinS_date ({year=year, month=month, day=day, year2=year2, month2=month2, day2=day2}, tCOinS_date); -- make an ISO 8601 date string for COinS
end
return true, anchor_year; -- format is good and date string represents a real date
end
--[[--------------------------< D A T E S >--------------------------------------------------------------------
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns
true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in
the COinS metadata) are derived. The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords "n.d." or "nd" (without quotes).
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,
a single error message is created as the dates are tested.
]]
local function dates(date_parameters_list, tCOinS_date)
local anchor_year; -- will return as nil if the date being tested is not |date=
local COinS_date; -- will return as nil if the date being tested is not |date=
local error_message = "";
local good_date = false;
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v) then -- if the parameter has a value
if v:match("^c%. [1-9]%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
local year = v:match("c%. ([1-9]%d%d%d?)%a?"); -- get the year portion so it can be tested
if 'date'==k then
anchor_year, COinS_date = v:match("((c%. [1-9]%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter
good_date = is_valid_year(year);
elseif 'year'==k then
good_date = is_valid_year(year);
end
elseif 'date'==k then -- if the parameter is |date=
if v:match("^n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; no error when date parameter is set to no date
elseif v:match("^nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date
else
good_date, anchor_year, COinS_date = check_date (v, tCOinS_date); -- go test the date
end
elseif 'access-date'==k then -- if the parameter is |date=
good_date = check_date (v); -- go test the date
if true == good_date then -- if the date is a valid date
good_date = is_valid_accessdate (v); -- is Wikipedia start date < accessdate < tomorrow's date?
end
else -- any other date-holding parameter
good_date = check_date (v); -- go test the date
end
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "|" .. k .. "="; -- add the failed parameter
end
end
end
return anchor_year, error_message; -- and done
end
--[[--------------------------< Y E A R _ D A T E _ C H E C K >------------------------------------------------
Compare the value provided in |year= with the year value(s) provided in |date=. This function returns a numeric value:
0 - year value does not match the year value in date
1 - (default) year value matches the year value in date or one of the year values when date contains two years
2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)
]]
local function year_date_check (year_string, date_string)
local year;
local date1;
local date2;
local result = 1; -- result of the test; assume that the test passes
year = year_string:match ('(%d%d%d%d?)');
if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then --special case where date and year required YYYY-MM-DD and YYYYx
date1 = date_string:match ('(%d%d%d%d)');
year = year_string:match ('(%d%d%d%d)');
if year ~= date1 then
result = 0; -- years don't match
else
result = 2; -- years match; but because disambiguated, don't add to maint cat
end
elseif date_string:match ("%d%d%d%d?.-%d%d%d%d?") then -- any of the standard formats of date with two three- or four-digit years
date1, date2 = date_string:match ("(%d%d%d%d?).-(%d%d%d%d?)");
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d[%s%-–]+%d%d") then -- YYYY-YY date ranges
local century;
date1, century, date2 = date_string:match ("((%d%d)%d%d)[%s%-–]+(%d%d)");
date2 = century..date2; -- convert YY to YYYY
if year ~= date1 and year ~= date2 then
result = 0;
end
elseif date_string:match ("%d%d%d%d?") then -- any of the standard formats of date with one year
date1 = date_string:match ("(%d%d%d%d?)");
if year ~= date1 then
result = 0;
end
end
return result;
end
return {dates = dates, year_date_check = year_date_check, is_valid_date_from_a_point = is_valid_date_from_a_point}
-- return exported functions
ed984e5750e25e443f23ede2446e5932e2e0d0a4
Module:Citation/CS1/Identifiers
828
179
365
364
2024-08-04T12:22:00Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, wrap_style; -- functions in Module:Citation/CS1/Utilities
local append_error, set_error, throw_error, select_one, add_maint_cat; -- functions in Module:Citation/CS1/Error
local make_internal_link; -- functions in Module:Citation/CS1/Links
local is_valid_date_from_a_point; -- functions in Module:Citation/CS1/Date_validation
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
local wd_int_lang = (mw.site.server:match ('wikidata') and mw.getCurrentFrame():preprocess('{{int:lang}}')) or '';
--============================<< H E L P E R F U N C T I O N S >>============================================
--[[--------------------------< E X T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki style external link
警告:该函数与英文站CS1模块中相应函数不兼容,请勿盲目替换!
]]
local function external_link_id(options)
local url_string = options.link_id or options.id;
local ext_link;
if options.encode == true or options.encode == nil then
url_string = mw.uri.encode( url_string );
end
ext_link = mw.ustring.format( '[%s%s%s <span title=\"%s\">%s%s%s</span>]',
options.prefix, url_string, options.suffix or "",
options.link, options.label, options.separator or " ",
mw.text.nowiki(options.id)
);
if is_set (options.access) then
ext_link = wrap_style ('access-signal', {ext_link, cfg.presentation[options.access]}); -- add the free-to-read / paywall lock
end
return ext_link;
end
--[[--------------------------< I N T E R N A L _ L I N K _ I D >----------------------------------------------
Formats a wiki style internal link
]]
local function internal_link_id(options)
return mw.ustring.format( '[[%s%s%s|<span title=\"%s\">%s</span>%s%s]]',
options.prefix, options.id, options.suffix or "",
options.link, options.label, options.separator or " ",
mw.text.nowiki(options.id)
);
end
--[[--------------------------< I S _ E M B A R G O E D >------------------------------------------------------
Determines if a PMC identifier's online version is embargoed. Compares the date in |embargo= against today's date. If embargo date is
in the future, returns the content of |embargo=; otherwise, returns and empty string because the embargo has expired or because
|embargo= was not set in this cite.
]]
local function is_embargoed (embargo)
if is_set (embargo) then
local lang = mw.getContentLanguage();
local good1, embargo_date, good2, todays_date;
good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );
good2, todays_date = pcall( lang.formatDate, lang, 'U' );
if good1 and good2 then -- if embargo date and today's date are good dates
if tonumber( embargo_date ) >= tonumber( todays_date ) then -- is embargo date is in the future?
return embargo; -- still embargoed
else
add_maint_cat ('embargo')
return ''; -- unset because embargo has expired
end
end
end
return ''; -- |embargo= not set return empty string
end
--[[--------------------------< IS _ V A L I D _ C H I N E S E _ B O O K _ C A T E G O R Y >----------------------
检查是否为GB/T 9999.1-2018附表B.1规定的合法图书分类
]]
local function is_valid_Chinese_book_category (str)
return in_array (str, {
"A",
"B", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B80", "B82", "B83", "B84", "B9",
"C", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C91", "C92", "C93", "C94", "C95", "C96", "C97",
"D", "D0", "D1", "D2", "D33", "D4", "D5", "D6", "D73", "D8", "D9", "DF",
"E", "E0", "E1", "E2", "E3", "E8", "E9", "E99",
"F", "F0", "F1", "F2", "F3", "F4", "F49", "F5", "F59", "F6", "F7", "F8",
"G", "G0", "G1", "G2", "G3", "G4", "G8",
"H", "H0", "H1", "H2", "H3", "H4", "H5", "H61", "H62", "H63", "H64", "H65", "H66", "H67", "H7", "H81", "H83", "H84", "H9",
"I", "I0", "I1", "I2", "I3", "I7",
"J", "J0", "J1", "J19", "J2", "J29", "J3", "J4", "J5", "J59", "J6", "J7", "J8", "J9",
"K", "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7", "K81", "K85", "K89", "K9",
"N", "N0", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N79", "N8", "N91", "N93", "N94", "N99",
"O", "O1", "O3", "O4", "O6", "O7",
"P", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P9",
"Q", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7", "Q81", "Q89", "Q91", "Q93", "Q94", "Q95", "Q96", "Q98",
"R", "R1", "R2", "R3", "R4", "R5", "R6", "R71", "R72", "R73", "R74", "R75", "R76", "R77", "R78", "R79", "R8", "R9",
"S", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
"T", "TB", "TD", "TE", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TP", "TQ", "TS", "TU", "TV",
"U", "U1", "U2", "U4", "U6", "U8",
"V", "V1", "V2", "V4", "V7",
"X", "X1", "X2", "X3", "X4", "X5", "X7", "X8", "X9",
"Z"
});
end
--[[--------------------------< IS _ V A L I D _ I S X N >-----------------------------------------------------
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit.
ISBN-13 is checked in isbn().
If the number is valid the result will be 0. Before calling this function, issbn/issn must be checked for length
and stripped of dashes, spaces and other non-isxn characters.
]]
local function is_valid_isxn (isxn_str, len)
local temp = 0;
isxn_str = { isxn_str:byte(1, len) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39, 'X' → 0x58
len = len+1; -- adjust to be a loop counter
for i, v in ipairs( isxn_str ) do -- loop through all of the bytes and calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X (compares the byte value of 'X' which is 0x58)
temp = temp + 10*( len - i ); -- it represents 10 decimal
else
temp = temp + tonumber( string.char(v) )*(len-i);
end
end
return temp % 11 == 0; -- returns true if calculation result is zero
end
--[[--------------------------< IS _ V A L I D _ I S X N _ 1 3 >-----------------------------------------------
ISBN-13 and ISMN validator code calculates checksum across all 13 isbn/ismn digits including the check digit.
If the number is valid, the result will be 0. Before calling this function, isbn-13/ismn must be checked for length
and stripped of dashes, spaces and other non-isxn-13 characters.
]]
local function is_valid_isxn_13 (isxn_str)
local temp=0;
isxn_str = { isxn_str:byte(1, 13) }; -- make a table of byte values '0' → 0x30 .. '9' → 0x39
for i, v in ipairs( isxn_str ) do
temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) ); -- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit
end
return temp % 10 == 0; -- sum modulo 10 is zero when isbn-13/ismn is correct
end
--[[--------------------------< N O R M A L I Z E _ L C C N >--------------------------------------------------
lccn normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization)
1. Remove all blanks.
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.
3. If there is a hyphen in the string:
a. Remove it.
b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):
1. All these characters should be digits, and there should be six or less. (not done in this function)
2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.
Returns a normalized lccn for lccn() to validate. There is no error checking (step 3.b.1) performed in this function.
]]
local function normalize_lccn (lccn)
lccn = lccn:gsub ("%s", ""); -- 1. strip whitespace
if nil ~= string.find (lccn,'/') then
lccn = lccn:match ("(.-)/"); -- 2. remove forward slash and all character to the right of it
end
local prefix
local suffix
prefix, suffix = lccn:match ("(.+)%-(.+)"); -- 3.a remove hyphen by splitting the string into prefix and suffix
if nil ~= suffix then -- if there was a hyphen
suffix=string.rep("0", 6-string.len (suffix)) .. suffix; -- 3.b.2 left fill the suffix with 0s if suffix length less than 6
lccn=prefix..suffix; -- reassemble the lccn
end
return lccn;
end
--============================<< I D E N T I F I E R F U N C T I O N S >>====================================
--[[--------------------------< A R X I V >--------------------------------------------------------------------
See: http://arxiv.org/help/arxiv_identifier
format and error check arXiv identifier. There are three valid forms of the identifier:
the first form, valid only between date codes 9108 and 0703 is:
arXiv:<archive>.<class>/<date code><number><version>
where:
<archive> is a string of alpha characters - may be hyphenated; no other punctuation
<class> is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
first digit of YY for this form can only 9 and 0
<number> is a three-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)
the second form, valid from April 2007 through December 2014 is:
arXiv:<date code>.<number><version>
where:
<date code> is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01
<number> is a four-digit number
<version> is a 1 or more digit number preceded with a lowercase v; no spaces
the third form, valid from January 2015 is:
arXiv:<date code>.<number><version>
where:
<date code> and <version> are as defined for 0704-1412
<number> is a five-digit number
]]
local function arxiv (id, class)
local handler = cfg.id_handlers['ARXIV'];
local year, month, version;
local err_cat = false; -- assume no error message
local text; -- output text
if id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$") or id:match("^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$") then -- test for the 9108-0703 format w/ & w/o version
year, month = id:match("^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((not (90 < year or 8 > year)) or (1 > month or 12 < month)) or -- if invalid year or invalid month
((91 == year and 7 > month) or (7 == year and 3 < month)) then -- if years ok, are starting and ending months ok?
err_cat = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%dv%d+$") then -- test for the 0704-1412 w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((7 > year) or (14 < year) or (1 > month or 12 < month)) or -- is year invalid or is month invalid? (doesn't test for future years)
((7 == year) and (4 > month)) then --or -- when year is 07, is month invalid (before April)?
err_cat = true; -- flag for error message
end
elseif id:match("^%d%d[01]%d%.%d%d%d%d%d$") or id:match("^%d%d[01]%d%.%d%d%d%d%dv%d+$") then -- test for the 1501- format w/ & w/o version
year, month = id:match("^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$");
year = tonumber(year);
month = tonumber(month);
if ((15 > year) or (1 > month or 12 < month)) then -- is year invalid or is month invalid? (doesn't test for future years)
err_cat = true; -- flag for error message
end
else
err_cat = true; -- not a recognized format; flag for error message
end
err_cat = err_cat and table.concat ({' ', set_error ('bad_arxiv')}) or ''; -- set error message if flag is true
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
if is_set (class) then
if id:match ('^%d+') then
text = table.concat ({text, ' [[//arxiv.org/archive/', class, ' ', class, ']]'}); -- external link within square brackets, not wikilink
else
text = table.concat ({text, ' ', set_error ('class_ignored')});
end
end
return text;
end
--[[--------------------------< B I B C O D E >--------------------------------------------------------------------
Validates (sort of) and formats a bibcode id.
Format for bibcodes is specified here: http://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes
But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters
and first four digits must be a year. This function makes these tests:
length must be 19 characters
characters in position
1–4 must be digits and must represent a year in the range of 1000 – next year
5 must be a letter
6 must be letter, ampersand, or dot (ampersand cannot directly precede a dot; &. )
7–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &. )
9–18 must be letter, digit, or dot
19 must be a letter or dot
]]
local function bibcode (id, access)
local handler = cfg.id_handlers['BIBCODE'];
local err_type;
local year;
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode,
access=access});
if 19 ~= id:len() then
err_type = 'length';
else
year = id:match ("^(%d%d%d%d)[%a][%a&%.][%a&%.%d][%a&%.%d][%a%d%.]+[%a%.]$") --
if not year then -- if nil then no pattern match
err_type = 'value'; -- so value error
else
local next_year = tonumber(os.date ('%Y'))+1; -- get the current year as a number and add one for next year
year = tonumber (year); -- convert year portion of bibcode to a number
if (1000 > year) or (year > next_year) then
err_type = 'year'; -- year out of bounds
end
if id:find('&%.') then
err_type = 'journal'; -- journal abbreviation must not have '&.' (if it does its missing a letter)
end
end
end
if is_set (err_type) then -- if there was an error detected
text = text .. ' ' .. set_error( 'bad_bibcode', {err_type});
end
return text;
end
--[[--------------------------< B I O R X I V >-----------------------------------------------------------------
Format bioRxiv id and do simple error checking. BiorXiv ids are exactly 6 digits.
The bioRxiv id is the number following the last slash in the bioRxiv-issued DOI:
https://doi.org/10.1101/078733 -> 078733
2019年底,biorxiv更换新格式,故而有必要兼容新旧两种格式,对该函数作出针对性修改
]]
local function biorxiv (id)
local handler = cfg.id_handlers['BIORXIV'];
local err_cat = ''; -- presume that bioRxiv id is valid
local invalid = false;
id = id:gsub ("^10.1101/",""); -- doi前缀10.1101/可填可不填,便利用户使用
if nil == id:match ("^%d%d%d%d%d%d$") then -- 不是旧格式
local date_str;
if (nil ~= id:match ("^%d%d%d%d%.[01]%d%.[0-3]%d%.%d%d%d%d%d%d$")) then
date_str = id:match ("^(%d%d%d%d%.[01]%d%.[0-3]%d)%.%d%d%d%d%d%d$");
else
if (nil ~= id:match ("^%d%d%d%d%.[01]%d%.[0-3]%d%.%d%d%d%d%d%dv%d+$")) then
date_str = id:match ("^(%d%d%d%d%.[01]%d%.[0-3]%d)%.%d%d%d%d%d%dv%d+$");
else -- 也不匹配新格式,因而为非法格式
invalid = true;
end
end
if (not invalid) then
date_str = date_str:gsub ("%.", "-");
if(not is_valid_date_from_a_point(date_str, 1576022400)) then
invalid = true;
end
end
end
if (invalid) then
err_cat = ' ' .. set_error( 'bad_biorxiv'); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix = handler.prefix, id = "10.1101/" .. id, separator = handler.separator,
encode = handler.encode, access = handler.access}) .. err_cat;
end
--[[--------------------------< C I T E S E E R X >------------------------------------------------------------
CiteSeerX use their own notion of "doi" (not to be confused with the identifiers resolved via doi.org).
The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure
]]
local function citeseerx (id)
local handler = cfg.id_handlers['CITESEERX'];
local matched;
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode,
access=handler.access});
matched = id:match ("^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$");
if not matched then
text = text .. ' ' .. set_error( 'bad_citeseerx' );
end
return text;
end
--[[--------------------------< C N I D >----------------------------------------------------------------------
判断国内统一刊号的合法性及输出相关内容
]]
local function cnid (id)
local handler = cfg.id_handlers['CNID'];
local text;
local type = 0;
local invalid = false;
local AA, BBBB, CC;
id = id:gsub ("^CN ?", "");
if nil ~= id:match ("^%d%d%-%d%d%d%d$") then
AA, BBBB = id:match ("^(%d%d)%-(%d%d%d%d)$");
else
if nil ~= id:match ("^%d%d%-%d%d%d%d/[A-Z0-9]+$") then
AA, BBBB, CC = id:match ("^(%d%d)%-(%d%d%d%d)/([A-Z0-9]+)$")
else invalid = true;
end
end
if (not invalid) then
if not in_array (AA, {"09", "10", "11", -- 北京
"12", "13", "14", "15", -- 华北
"21", "22", "23", -- 东北
"30", "31", "32", "33", "34", "35", "36", "37", -- 华东
"41", "42", "43", "44", "45", "46", -- 华中华南
"50", "51", "52", "53", "54", -- 西南
"61", "62", "63", "64", "65" -- 西北
}) then
invalid = true ;
else
local BBBB_num = tonumber (BBBB);
if (BBBB_num >= 1 and BBBB_num <= 999) then
type = 1;
if (nil ~= CC) then
invalid = true;
end;
else
if (BBBB_num >= 1000 and BBBB_num <= 5999) then
type = 2;
if (not is_valid_Chinese_book_category (CC)) then
invalid = true;
end
else
type = 3;
if (nil ~= CC and not is_valid_Chinese_book_category (CC)) then
invalid = true;
end
end
end
end
end
if (not invalid) and (1 == type) then
local link_id = id:gsub ("-","");
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix, suffix = "&typeNum=1",
link_id = link_id, id = id,
separator = handler.separator, encode = handler.encode});
else
if (not invalid) and (2 == type) then
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix, suffix = "&typeNum=2",
id = id, separator = handler.separator, encode = handler.encode});
else
text = mw.ustring.format( "<span title=\"%s\">%s%s%s</span>",
handler.link, handler.label, handler.separator,
mw.text.nowiki (id)
);
end
end
if (invalid) then
text = text .. ' ' .. set_error( 'bad_cnid');
end
return text;
end
--[[--------------------------< C S B N >----------------------------------------------------------------------
判断CSBN的合法性及产生指向豆瓣网的链接。
CSBN格式参考《谈谈国家统一书号与国际标准书号》及最新实例。
]]
local function csbn_checkCatNum (cat)
local cat_num = tonumber(cat)
return not (cat_num <=0 or cat_num >17) -- 若分类号取值不在1-17范围内,则不合法。
end
local function csbn (id)
local handler = cfg.id_handlers['CSBN'];
local text;
local invalid = false;
id = id:gsub ("%-","·");
if (nil == id:match ("^[1-9]%d?%d?%d?%d%d%d·%d+$")) then
-- CSBN由三部分组成,第一部分为中国人民大学图书分类法代号,取值1-17(前缀不补零);
-- 第二部分为出版社代号,三到五位;第三部分为种次号,取值不限。
-- 二、三部分间有小圆点;若取值不合该格式,则不合法。
-- 此外,虽然小圆点用"-"取代不合规定,但误用较多,亦有出版物采用,故兼容。
invalid = true;
else
local catNumOk = nil
local category
category = id:match ("^([1-9]%d-)%d?%d?%d%d%d·%d+$"); -- Lua无法非贪婪特定部分或指定重复次数,分别检查
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
category = id:match ("^([1-9]%d-)%d?%d%d%d·%d+$");
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
category = id:match ("^([1-9]%d-)d%d%d·%d+$");
if (nil == catNumOk and nil ~= category) then catNumOk = csbn_checkCatNum(category) end
invalid = not catNumOk;
end
-- 豆瓣网以连接号取代小圆点,故替换之。
local link_id = id:gsub ("·","%-");
text = external_link_id({link = handler.link, label = handler.label,
q = handler.q, prefix = handler.prefix,
link_id = link_id, id = id,
separator = handler.separator, encode = handler.encode});
if (invalid) then
text = text .. ' ' .. set_error( 'bad_csbn');
end
return text;
end
--[[--------------------------< D O I >------------------------------------------------------------------------
Formats a DOI and checks for DOI errors.
DOI names contain two parts: prefix and suffix separated by a forward slash.
Prefix: directory indicator '10.' followed by a registrant code
Suffix: character string of any length chosen by the registrant
This function checks a DOI name for: prefix/suffix. If the doi name contains spaces or endashes, or, if it ends
with a period or a comma, this function will emit a bad_doi error message.
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in doi names.
]]
local function doi(id, inactive, access)
local cat = ""
local handler = cfg.id_handlers['DOI'];
local text;
if is_set(inactive) then
local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date
if is_set(inactive_year) then
set_error('doi_inactive_dated', {inactive_year});
else
set_error('doi_inactive'); -- when inactive doesn't contain a recognizable year
end
inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=access}) .. (inactive or '')
if nil == id:match("^10%.[^%s–]-/[^%s–]-[^%.,]$") then -- doi must begin with '10.', must contain a fwd slash, must not contain spaces or endashes, and must not end with period or comma
cat = ' ' .. set_error( 'bad_doi' );
end
return text .. cat
end
--[[--------------------------< H D L >------------------------------------------------------------------------
Formats an HDL with minor error checking.
HDL names contain two parts: prefix and suffix separated by a forward slash.
Prefix: character string using any character in the UCS-2 character set except '/'
Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant
This function checks a HDL name for: prefix/suffix. If the HDL name contains spaces, endashes, or, if it ends
with a period or a comma, this function will emit a bad_hdl error message.
HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and
terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely
if ever used in HDLs.
]]
local function hdl(id, access)
local handler = cfg.id_handlers['HDL'];
local text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=access})
if nil == id:match("^[^%s–]-/[^%s–]-[^%.,]$") then -- hdl must contain a fwd slash, must not contain spaces, endashes, and must not end with period or comma
text = text .. ' ' .. set_error( 'bad_hdl' );
end
return text;
end
--[[--------------------------< I S B N >----------------------------------------------------------------------
Determines whether an ISBN string is valid
]]
local function isbn( isbn_str )
if nil ~= isbn_str:match("[^%s-0-9X]") then
return false, 'invalid character'; -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
end
isbn_str = isbn_str:gsub( "-", "" ):gsub( " ", "" ); -- remove hyphens and spaces
local len = isbn_str:len();
if len ~= 10 and len ~= 13 then
return false, 'length'; -- fail if incorrect length
end
if len == 10 then
if isbn_str:match( "^%d*X?$" ) == nil then -- fail if isbn_str has 'X' anywhere but last position
return false, 'invalid form';
end
return is_valid_isxn(isbn_str, 10), 'checksum';
else
if isbn_str:match( "^%d+$" ) == nil then
return false, 'invalid character'; -- fail if isbn13 is not all digits
end
if isbn_str:match( "^97[89]%d*$" ) == nil then
return false, 'invalid prefix'; -- fail when isbn13 does not begin with 978 or 979
end
return is_valid_isxn_13 (isbn_str), 'checksum';
end
end
--[[--------------------------< A M A Z O N >------------------------------------------------------------------
Formats a link to Amazon. Do simple error checking: asin must be mix of 10 numeric or uppercase alpha
characters. If a mix, first character must be uppercase alpha; if all numeric, asins must be 10-digit
isbn. If 10-digit isbn, add a maintenance category so a bot or awb script can replace |asin= with |isbn=.
Error message if not 10 characters, if not isbn10, if mixed and first character is a digit.
This function is positioned here because it calls isbn()
]]
local function asin(id, domain)
local err_cat = ""
if not id:match("^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then
err_cat = ' ' .. set_error ('bad_asin'); -- asin is not a mix of 10 uppercase alpha and numeric characters
else
if id:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then -- if 10-digit numeric (or 9 digits with terminal X)
if isbn( id ) then -- see if asin value is isbn10
add_maint_cat ('ASIN');
elseif not is_set (err_cat) then
err_cat = ' ' .. set_error ('bad_asin'); -- asin is not isbn10
end
elseif not id:match("^%u[%d%u]+$") then
err_cat = ' ' .. set_error ('bad_asin'); -- asin doesn't begin with uppercase alpha
end
end
if not is_set(domain) then
domain = "com";
elseif in_array (domain, {'jp', 'uk'}) then -- Japan, United Kingdom
domain = "co." .. domain;
elseif in_array (domain, {'au', 'br', 'mx'}) then -- Australia, Brazil, Mexico
domain = "com." .. domain;
end
local handler = cfg.id_handlers['ASIN'];
return external_link_id({link=handler.link,
label=handler.label, q = handler.q, prefix=handler.prefix .. domain .. "/dp/",
id=id, encode=handler.encode, separator = handler.separator}) .. err_cat;
end
--[[--------------------------< I S M N >----------------------------------------------------------------------
Determines whether an ISMN string is valid. Similar to isbn-13, ismn is 13 digits begining 979-0-... and uses the
same check digit calculations. See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf
section 2, pages 9–12.
]]
local function ismn (id)
local handler = cfg.id_handlers['ISMN'];
local text;
local valid_ismn = true;
local id_copy;
id_copy = id; -- save a copy because this testing is destructive
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the ismn
if 13 ~= id:len() or id:match( "^9790%d*$" ) == nil then -- ismn must be 13 digits and begin 9790
valid_ismn = false;
else
valid_ismn=is_valid_isxn_13 (id); -- validate ismn
end
-- text = internal_link_id({link = handler.link, label = handler.label, -- use this (or external version) when there is some place to link to
-- prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
text="[[" .. handler.link .. "|" .. handler.label .. "]]" .. handler.separator .. id;
-- because no place to link to yet
if false == valid_ismn then
text = text .. ' ' .. set_error( 'bad_ismn' ) -- add an error message if the issn is invalid
end
return text;
end
--[[--------------------------< I S S N >----------------------------------------------------------------------
Validate and format an issn. This code fixes the case where an editor has included an ISSN in the citation but
has separated the two groups of four digits with a space. When that condition occurred, the resulting link looked
like this:
|issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327] -- can't have spaces in an external link
This code now prevents that by inserting a hyphen at the issn midpoint. It also validates the issn for length
and makes sure that the checkdigit agrees with the calculated value. Incorrect length (8 digits), characters
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check issn error message. The
issn is always displayed with a hyphen, even if the issn was given as a single group of 8 digits.
]]
local function issn(id, e)
local issn_copy = id; -- save a copy of unadulterated issn; use this version for display if issn does not validate
local handler;
local text;
local valid_issn = true;
if e then
handler = cfg.id_handlers['EISSN'];
else
handler = cfg.id_handlers['ISSN'];
end
id=id:gsub( "[%s-–]", "" ); -- strip spaces, hyphens, and endashes from the issn
if 8 ~= id:len() or nil == id:match( "^%d*X?$" ) then -- validate the issn: 8 digits long, containing only 0-9 or X in the last position
valid_issn=false; -- wrong length or improper character
else
valid_issn=is_valid_isxn(id, 8); -- validate issn
end
if true == valid_issn then
id = string.sub( id, 1, 4 ) .. "-" .. string.sub( id, 5 ); -- if valid, display correctly formatted version
else
id = issn_copy; -- if not valid, use the show the invalid issn with error message
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if false == valid_issn then
text = text .. ' ' .. set_error( 'bad_issn', e and 'e' or '' ) -- add an error message if the issn is invalid
end
return text
end
--[[--------------------------< J F M >-----------------------------------------------------------------------
A numerical identifier in the form nn.nnnn.nn
]]
local function jfm (id)
local handler = cfg.id_handlers['JFM'];
local id_num;
local err_cat = '';
id_num = id:match ('^[Jj][Ff][Mm](.*)$'); -- identifier with jfm prefix; extract identifier
if is_set (id_num) then
add_maint_cat ('jfm_format');
else -- plain number without mr prefix
id_num = id; -- if here id does not have prefix
end
if id_num and id_num:match('^%d%d%.%d%d%d%d%.%d%d$') then
id = id_num; -- jfm matches pattern
else
err_cat = ' ' .. set_error( 'bad_jfm' ); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< L C C N >----------------------------------------------------------------------
Format LCCN link and do simple error checking. LCCN is a character string 8-12 characters long. The length of
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.
http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:lccn/
length = 8 then all digits
length = 9 then lccn[1] is lower case alpha
length = 10 then lccn[1] and lccn[2] are both lower case alpha or both digits
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lower case alpha or both digits
length = 12 then lccn[1] and lccn[2] are both lower case alpha
]]
local function lccn(lccn)
local handler = cfg.id_handlers['LCCN'];
local err_cat = ''; -- presume that LCCN is valid
local id = lccn; -- local copy of the lccn
id = normalize_lccn (id); -- get canonical form (no whitespace, hyphens, forward slashes)
local len = id:len(); -- get the length of the lccn
if 8 == len then
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits)
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 9 == len then -- LCCN should be adddddddd
if nil == id:match("%l%d%d%d%d%d%d%d%d") then -- does it match our pattern?
err_cat = ' ' .. set_error( 'bad_lccn' ); -- set an error message
end
elseif 10 == len then -- LCCN should be aadddddddd or dddddddddd
if id:match("[^%d]") then -- if LCCN has anything but digits (nil if only digits) ...
if nil == id:match("^%l%l%d%d%d%d%d%d%d%d") then -- ... see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
end
elseif 11 == len then -- LCCN should be aaadddddddd or adddddddddd
if not (id:match("^%l%l%l%d%d%d%d%d%d%d%d") or id:match("^%l%d%d%d%d%d%d%d%d%d%d")) then -- see if it matches one of our patterns
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
elseif 12 == len then -- LCCN should be aadddddddddd
if not id:match("^%l%l%d%d%d%d%d%d%d%d%d%d") then -- see if it matches our pattern
err_cat = ' ' .. set_error( 'bad_lccn' ); -- no match, set an error message
end
else
err_cat = ' ' .. set_error( 'bad_lccn' ); -- wrong length, set an error message
end
if not is_set (err_cat) and nil ~= lccn:find ('%s') then
err_cat = ' ' .. set_error( 'bad_lccn' ); -- lccn contains a space, set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=lccn,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< M R >--------------------------------------------------------------------------
A seven digit number; if not seven digits, zero-fill leading digits to make seven digits.
]]
local function mr (id)
local handler = cfg.id_handlers['MR'];
local id_num;
local id_len;
local err_cat = '';
id_num = id:match ('^[Mm][Rr](%d+)$'); -- identifier with mr prefix
if is_set (id_num) then
add_maint_cat ('mr_format');
else -- plain number without mr prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
id_len = id_num and id_num:len() or 0;
if (7 >= id_len) and (0 ~= id_len) then
id = string.rep ('0', 7-id_len ) .. id_num; -- zero-fill leading digits
else
err_cat = ' ' .. set_error( 'bad_mr' ); -- set an error message
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< O C L C >----------------------------------------------------------------------
Validate and format an oclc id. https://www.oclc.org/batchload/controlnumber.en.html {{dead link}}
archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html
]]
local function oclc (id)
local handler = cfg.id_handlers['OCLC'];
local number;
local err_msg = ''; -- empty string for concatenation
if id:match('^ocm%d%d%d%d%d%d%d%d$') then -- ocm prefix and 8 digits; 001 field (12 characters)
number = id:match('ocm(%d+)'); -- get the number
elseif id:match('^ocn%d%d%d%d%d%d%d%d%d$') then -- ocn prefix and 9 digits; 001 field (12 characters)
number = id:match('ocn(%d+)'); -- get the number
elseif id:match('^on%d%d%d%d%d%d%d%d%d%d+$') then -- on prefix and 10 or more digits; 001 field (12 characters)
number = id:match('^on(%d%d%d%d%d%d%d%d%d%d+)$'); -- get the number
elseif id:match('^%(OCoLC%)[1-9]%d*$') then -- (OCoLC) prefix and variable number digits; no leading zeros; 035 field
number = id:match('%(OCoLC%)([1-9]%d*)'); -- get the number
if 9 < number:len() then
number = nil; -- contrain to 1 to 9 digits; change this when oclc issues 10-digit numbers
end
elseif id:match('^%d+$') then -- no prefix
number = id; -- get the number
if 10 < number:len() then
number = nil; -- contrain to 1 to 10 digits; change this when oclc issues 11-digit numbers
end
end
if number then -- proper format
id = number; -- exclude prefix, if any, from external link
else
err_msg = ' ' .. set_error( 'bad_oclc' ) -- add an error message if the id is malformed
end
local text = external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix, id=id, separator=handler.separator, encode=handler.encode}) .. err_msg;
return text;
end
--[[--------------------------< O P E N L I B R A R Y >--------------------------------------------------------
Formats an OpenLibrary link, and checks for associated errors.
]]
local function openlibrary(id, access)
local code;
local handler = cfg.id_handlers['OL'];
local ident;
ident, code = id:match("^(%d+([AMW]))$"); -- optional OL prefix followed immediately by digits followed by 'A', 'M', or 'W'; remove OL prefix
if not is_set (ident) then -- if malformed return an error
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access}) .. ' ' .. set_error( 'bad_ol' );
end
id = ident; -- use ident without the optional OL prefix (it has been removed)
if ( code == "A" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'authors/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
if ( code == "M" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'books/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
if ( code == "W" ) then
return external_link_id({link=handler.link, label=handler.label, q = handler.q,
prefix=handler.prefix .. 'works/OL',
id=id, separator=handler.separator, encode = handler.encode,
access = access})
end
end
--[[--------------------------< P M C >------------------------------------------------------------------------
Format a PMC, do simple error checking, and check for embargoed articles.
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not
be linked to the article. If the embargo date is today or in the past, or if it is empty or omitted, then the
PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation
has |pmc=<value> but does not have a |url= then |title= is linked with the PMC link. Function is_embargoed ()
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.
PMCs are sequential numbers beginning at 1 and counting up. This code checks the PMC to see that it contains only digits and is less
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.
]]
local function pmc(id, embargo)
local test_limit = 12000000; -- update this value as PMCs approach
local handler = cfg.id_handlers['PMC'];
local err_cat = ''; -- presume that PMC is valid
local id_num;
local text;
id_num = id:match ('^[Pp][Mm][Cc](%d+)$'); -- identifier with pmc prefix
if is_set (id_num) then
add_maint_cat ('pmc_format');
else -- plain number without pmc prefix
id_num = id:match ('^%d+$'); -- if here id is all digits
end
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber(id_num); -- convert id_num to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMC is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
else
id = tostring (id_num); -- make sure id is a string
end
else -- when id format incorrect
err_cat = ' ' .. set_error( 'bad_pmc' ); -- set an error message
end
if is_set (embargo) then -- is PMC is still embargoed?
text = table.concat ( -- still embargoed so no external link
{
make_internal_link (handler.link, handler.label),
handler.separator,
id,
err_cat
});
else
text = external_link_id({link = handler.link, label = handler.label, q = handler.q, -- no embargo date or embargo has expired, ok to link to article
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
end
return text;
end
--[[--------------------------< P M I D >----------------------------------------------------------------------
Format PMID and do simple error checking. PMIDs are sequential numbers beginning at 1 and counting up. This
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable
test_limit will need to be updated periodically as more PMIDs are issued.
]]
local function pmid(id)
local test_limit = 40000000; -- update this value as PMIDs approach
local handler = cfg.id_handlers['PMID'];
local err_cat = ''; -- presume that PMID is valid
if id:match("[^%d]") then -- if PMID has anything but digits
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
else -- PMID is only digits
local id_num = tonumber(id); -- convert id to a number for range testing
if 1 > id_num or test_limit < id_num then -- if PMID is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_pmid' ); -- set an error message
end
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--[[--------------------------< S 2 C I D >--------------------------------------------------------------------
Format an S2CID, do simple error checking
S2CIDs are sequential numbers beginning at 1 and counting up. This code checks the S2CID to see that it is only
digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically
as more S2CIDs are issued.
]]
local function s2cid (id, access)
local test_limit = 300000000;
local handler = cfg.id_handlers['S2CID'];
local err_cat = ''; -- presume that S2CID is valid
local id_num = id:match ('^[1-9]%d*$'); -- id must be all digits; must not begin with 0; no open access flag
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber (id_num); -- convert id_num to a number for range testing
if test_limit < id_num then -- if S2CID is outside test limit boundaries
err_cat = ' ' .. set_error ('bad_s2cid'); -- set an error message
end
else -- when id format incorrect
err_cat = ' ' .. set_error ('bad_s2cid'); -- set an error message
end
return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,
prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access}) .. err_cat;
end
--[[--------------------------< S S R N >----------------------------------------------------------------------
Format an ssrn, do simple error checking
SSRNs are sequential numbers beginning at 100? and counting up. This code checks the ssrn to see that it is
only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need
to be updated periodically as more SSRNs are issued.
]]
local function ssrn (id)
local test_limit = 3500000; -- update this value as SSRNs approach
local handler = cfg.id_handlers['SSRN'];
local err_cat = ''; -- presume that SSRN is valid
local id_num;
local text;
id_num = id:match ('^%d+$'); -- id must be all digits
if is_set (id_num) then -- id_num has a value so test it
id_num = tonumber(id_num); -- convert id_num to a number for range testing
if 100 > id_num or test_limit < id_num then -- if SSRN is outside test limit boundaries
err_cat = ' ' .. set_error( 'bad_ssrn' ); -- set an error message
end
else -- when id format incorrect
err_cat = ' ' .. set_error( 'bad_ssrn' ); -- set an error message
end
text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode, access=handler.access}) .. err_cat;
return text;
end
--[[--------------------------< U S E N E T _ I D >------------------------------------------------------------
Validate and format a usenet message id. Simple error checking, looks for 'id-left@id-right' not enclosed in
'<' and/or '>' angle brackets.
]]
local function usenet_id (id)
local handler = cfg.id_handlers['USENETID'];
local text = external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
if not id:match('^.+@.+$') or not id:match('^[^<].*[^>]$')then -- doesn't have '@' or has one or first or last character is '< or '>'
text = text .. ' ' .. set_error( 'bad_message_id' ) -- add an error message if the message id is invalid
end
return text
end
--[[--------------------------< Z B L >-----------------------------------------------------------------------
A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional
]]
local function zbl (id)
local handler = cfg.id_handlers['ZBL'];
local err_cat = '';
id = id:gsub ('^[Zz][Bb][Ll]',""); -- identifier with zbl prefix; extract identifier
if (nil ~= id:match ("^%d%d%d%d%d%d%d%d$")) then
add_maint_cat ('zbl_format'); -- temporary
else
if (nil == id:match('^%d?%d?%d?%d%.%d%d%d%d%d$')) then -- id doesn't match the pattern
err_cat = ' ' .. set_error( 'bad_zbl' ); -- set an error message
end
end
return external_link_id({link = handler.link, label = handler.label, q = handler.q,
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode}) .. err_cat;
end
--============================<< I N T E R F A C E F U N C T I O N S >>==========================================
--[[--------------------------< B U I L D _ I D _ L I S T >--------------------------------------------------------
Takes a table of IDs created by extract_ids() and turns it into a table of formatted ID outputs.
inputs:
id_list – table of identifiers built by extract_ids()
options – table of various template parameter values used to modify some manually handled identifiers
]]
local function build_id_list( id_list, options )
local new_list, handler = {};
local function fallback(k) return { __index = function(t,i) return cfg.id_handlers[k][i] end } end;
for k, v in pairs( id_list ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
-- fallback to read-only cfg
handler = setmetatable( { ['id'] = v, ['access'] = options.IdAccessLevels[k] }, fallback(k) );
if handler.mode == 'external' then
table.insert( new_list, {handler.label, external_link_id( handler ) } );
elseif handler.mode == 'internal' then
table.insert( new_list, {handler.label, internal_link_id( handler ) } );
elseif handler.mode ~= 'manual' then
throw_error( 'unknown_ID_mode' );
elseif k == 'ARXIV' then
table.insert( new_list, {handler.label, arxiv( v, options.Class ) } );
elseif k == 'ASIN' then
table.insert( new_list, {handler.label, asin( v, options.ASINTLD ) } );
elseif k == 'BIBCODE' then
table.insert( new_list, {handler.label, bibcode( v, handler.access ) } );
elseif k == 'BIORXIV' then
table.insert( new_list, {handler.label, biorxiv( v ) } );
elseif k == 'CITESEERX' then
table.insert( new_list, {handler.label, citeseerx( v ) } );
elseif k == 'CNID' then
table.insert( new_list, {handler.label, cnid( v ) } );
elseif k == 'CSBN' then
table.insert( new_list, {handler.label, csbn( v ) } );
elseif k == 'DOI' then
table.insert( new_list, {handler.label, doi( v, options.DoiBroken, handler.access ) } );
elseif k == 'EISSN' then
table.insert( new_list, {handler.label, issn( v, true ) } ); -- true distinguishes eissn from issn
elseif k == 'HDL' then
table.insert( new_list, {handler.label, hdl( v, handler.access ) } );
elseif k == 'ISBN' then
local ISBN = internal_link_id( handler );
local check;
local err_type = '';
check, err_type = isbn( v );
if not check then
if is_set(options.IgnoreISBN) then -- ISBN is invalid; if |ignore-isbn-error= set
add_maint_cat ('ignore_isbn_err'); -- ad a maint category
else
ISBN = ISBN .. set_error( 'bad_isbn', {err_type}, false, " ", "" ); -- else display an error message
end
elseif is_set(options.IgnoreISBN) then -- ISBN is OK; if |ignore-isbn-error= set
add_maint_cat ('ignore_isbn_err'); -- because |ignore-isbn-error= unnecessary
end
table.insert( new_list, {handler.label, ISBN } );
elseif k == 'ISMN' then
table.insert( new_list, {handler.label, ismn( v ) } );
elseif k == 'ISSN' then
table.insert( new_list, {handler.label, issn( v ) } );
elseif k == 'JFM' then
table.insert( new_list, {handler.label, jfm( v ) } );
elseif k == 'LCCN' then
table.insert( new_list, {handler.label, lccn( v ) } );
elseif k == 'MR' then
table.insert( new_list, {handler.label, mr( v ) } );
elseif k == 'OCLC' then
table.insert( new_list, {handler.label, oclc( v ) } );
elseif k == 'OL' or k == 'OLA' then
table.insert( new_list, {handler.label, openlibrary( v, handler.access ) } );
elseif k == 'PMC' then
table.insert( new_list, {handler.label, pmc( v, options.Embargo ) } );
elseif k == 'PMID' then
table.insert( new_list, {handler.label, pmid( v ) } );
elseif k == 'S2CID' then
table.insert( new_list, {handler.label, s2cid( v, handler.access ) } );
elseif k == 'SSRN' then
table.insert( new_list, {handler.label, ssrn( v ) } );
elseif k == 'USENETID' then
table.insert( new_list, {handler.label, usenet_id( v ) } );
elseif k == 'ZBL' then
table.insert( new_list, {handler.label, zbl( v ) } );
else
throw_error( 'unknown_manual_ID' );
end
end
local function comp( a, b ) -- used in following table.sort()
return a[1] < b[1];
end
table.sort( new_list, comp );
for k, v in ipairs( new_list ) do
new_list[k] = v[2];
end
return new_list;
end
--[[--------------------------< E X T R A C T _ I D S >------------------------------------------------------------
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for
any of the parameters listed in each cfg.id_handlers['...'].parameters. If found, adds the parameter and value to
the identifier list. Emits redundant error message is more than one alias exists in args
]]
local function extract_ids( args )
local id_list = {}; -- list of identifiers found in args
for k, v in pairs( cfg.id_handlers ) do -- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers['ISBN'], v is a table
v = select_one( args, v.parameters, 'redundant_parameters' ); -- v.parameters is a table of aliases for k; here we pick one from args if present
if is_set(v) then id_list[k] = v; end -- if found in args, add identifier to our list
end
return id_list;
end
--[[--------------------------< E X T R A C T _ I D _ A C C E S S _ L E V E L S >--------------------------------------
Fetches custom id access levels from arguments using configuration settings.
Parameters which have a predefined access level (e.g. arxiv) do not use this
function as they are directly rendered as free without using an additional parameter.
]]
local function extract_id_access_levels( args, id_list )
local id_accesses_list = {};
for k, v in pairs( cfg.id_handlers ) do
local access_param = v.custom_access;
local k_lower = string.lower(k);
if is_set(access_param) then
local access_level = args[access_param];
if is_set(access_level) then
if not in_array (access_level:lower(), cfg.keywords['id-access']) then
append_error( 'invalid_param_val', {access_param, access_level});
access_level = nil;
end
if not is_set(id_list[k]) then
append_error( 'param_access_requires_param', {k_lower});
end
if is_set(access_level) then
access_level = access_level:lower();
end
id_accesses_list[k] = access_level;
end
end
end
return id_accesses_list;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, error_page_ptr, links_page_ptr, validation_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
wrap_style = utilities_page_ptr.wrap_style;
append_error = error_page_ptr.append_error;
set_error = error_page_ptr.set_error;
throw_error = error_page_ptr.throw_error;
select_one = error_page_ptr.select_one;
add_maint_cat = error_page_ptr.add_maint_cat;
make_internal_link = links_page_ptr.make_internal_link;
is_valid_date_from_a_point = validation_page_ptr.is_valid_date_from_a_point;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
build_id_list = build_id_list,
extract_ids = extract_ids,
extract_id_access_levels = extract_id_access_levels,
is_embargoed = is_embargoed;
set_selected_modules = set_selected_modules;
}
b1d58a2f7f50e7581f1eb0fd0d2a6cf8012bb316
Module:Citation/CS1/Utilities
828
180
367
366
2024-08-04T12:22:00Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg; -- table of tables imported from selected Module:Citation/CS1/Configuration
--[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------
Converts a hyphen to a dash
]]
--
local function hyphen_to_dash( str )
if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then
return str;
end
return str:gsub( '-', '–' );
end
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
This function is global because it is called from both this module and from Date validation
]]
function is_set( var )
return not (var == nil or var == '');
end
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------
Locates and returns the first set value in a table of values where the order established in the table,
left-to-right (or top-to-bottom), is the order in which the values are evaluated. Returns nil if none are set.
This version replaces the original 'for _, val in pairs do' and a similar version that used ipairs. With the pairs
version the order of evaluation could not be guaranteed. With the ipairs version, a nil value would terminate
the for-loop before it reached the actual end of the list.
]]
local function first_set (list, count)
local i = 1;
while i <= count do -- loop through all items in list
if is_set( list[i] ) then
return list[i]; -- return the first set list member
end
i = i + 1; -- point to next
end
end
--[[--------------------------< I N _ A R R A Y >--------------------------------------------------------------
Whether needle is in haystack
]]
local function in_array( needle, haystack )
if needle == nil then
return false;
end
for n,v in ipairs( haystack ) do
if v == needle then
return n;
end
end
return false;
end
--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------
Populates numbered arguments in a message string using an argument table.
]]
local function substitute( msg, args )
return args and mw.message.newRawMessage( msg, args ):plain() or msg;
end
--[[--------------------------< H A S _ A C C E P T _ A S _ W R I T T E N >------------------------------------
When <str> is wholly wrapped in accept-as-written markup, return <str> without markup and true; return <str> and false else
with allow_empty = false, <str> must have at least one character inside the markup
with allow_empty = true, <str> the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition "has no applicable value" in citation-context.
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.
]]
local function has_accept_as_written (str, allow_empty)
local count;
if true == allow_empty then
str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); -- allows (()) to be an empty set
else
str, count = str:gsub ('^%(%((.+)%)%)$', '%1');
end
return str, 0 ~= count;
end
--[[--------------------------< S A F E _ F O R _ I T A L I C S >----------------------------------------------
Protects a string that will be wrapped in wiki italic markup '' ... ''
Note: We cannot use <i> for italics, as the expected behavior for italics specified by ''...'' in the title is that
they will be inverted (i.e. unitalicized) in the resulting references. In addition, <i> and '' tend to interact
poorly under Mediawiki's HTML tidy.
]]
local function safe_for_italics (str)
if not is_set (str) then return str end
if str:sub (1, 1) == "'" then str = "<span></span>" .. str; end
if str:sub (-1, -1) == "'" then str = str .. "<span></span>"; end
-- Remove newlines as they break italics.
return str:gsub ('\n', ' ');
end
--[[--------------------------< W R A P _ S T Y L E >----------------------------------------------------------
Applies styling to various parameters. Supplied string is wrapped using a message_list configuration taking one
argument; protects italic styled parameters. Additional text taken from citation_config.presentation - the reason
this function is similar to but separate from wrap_msg().
]]
local function wrap_style (key, str)
if not is_set (str) then
return '';
elseif in_array (key, cfg.presentation['_safe_for_italics']) then
str = safe_for_italics (str);
end
return substitute (cfg.presentation[key], str);
end
--[[--------------------------< M A K E _ S E P _ L I S T >------------------------------------------------------------
make a separated list of items using provided separators.
<sep_list> - typically '<comma><space>'
<sep_list_pair> - typically '<space>and<space>'
<sep_list_end> - typically '<comma><space>and<space>' or '<comma><space>&<space>'
defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']
if <sep_list_end> is specified, <sep_list> and <sep_list_pair> must also be supplied
]]
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)
local list = '';
if not sep_list then -- set the defaults
sep_list = cfg.presentation['sep_list'];
sep_list_pair = cfg.presentation['sep_list_pair'];
sep_list_end = cfg.presentation['sep_list_end'];
end
if 2 >= count then
list = table.concat (list_seq, sep_list_pair); -- insert separator between two items; returns list_seq[1] then only one item
elseif 2 < count then
list = table.concat (list_seq, sep_list, 1, count - 1); -- concatenate all but last item with plain list separator
list = table.concat ({list, list_seq[count]}, sep_list_end); -- concatenate last item onto end of <list> with final separator
end
return list;
end
--[[--------------------------< S A F E _ J O I N >------------------------------------------------------------
Joins a sequence of strings together while checking for duplicate separation characters.
]]
local function safe_join( tbl, duplicate_char )
--[[
Note: we use string functions here, rather than ustring functions.
This has considerably faster performance and should work correctly as
long as the duplicate_char is strict ASCII. The strings
in tbl may be ASCII or UTF8.
]]
local str = ''; -- the output string
local comp = ''; -- what does 'comp' mean?
local end_chr = '';
local trim;
for _, value in ipairs( tbl ) do
if value == nil then value = ''; end
if str == '' then -- if output string is empty
str = value; -- assign value to it (first time through the loop)
elseif value ~= '' then
if value:sub(1,1) == '<' then -- Special case of values enclosed in spans and other markup.
comp = value:gsub( "%b<>", "" ); -- remove html markup (<span>string</span> -> string)
else
comp = value;
end
-- typically duplicate_char is sepc
if comp:sub(1,1) == duplicate_char then -- is first charactier same as duplicate_char? why test first character?
-- Because individual string segments often (always?) begin with terminal punct for th
-- preceding segment: 'First element' .. 'sepc next element' .. etc?
trim = false;
end_chr = str:sub(-1,-1); -- get the last character of the output string
-- str = str .. "<HERE(enchr=" .. end_chr.. ")" -- debug stuff?
if end_chr == duplicate_char then -- if same as separator
str = str:sub(1,-2); -- remove it
elseif end_chr == "'" then -- if it might be wikimarkup
if str:sub(-3,-1) == duplicate_char .. "''" then -- if last three chars of str are sepc''
str = str:sub(1, -4) .. "''"; -- remove them and add back ''
elseif str:sub(-5,-1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]''
trim = true; -- why? why do this and next differently from previous?
elseif str:sub(-4,-1) == duplicate_char .. "]''" then -- if last four chars of str are sepc]''
trim = true; -- same question
end
elseif end_chr == "]" then -- if it might be wikimarkup
if str:sub(-3,-1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink
trim = true;
elseif str:sub(-2,-1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link
trim = true;
elseif str:sub(-4,-1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title.
trim = true;
end
elseif end_chr == " " then -- if last char of output string is a space
if str:sub(-2,-1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space>
str = str:sub(1,-3); -- remove them both
end
end
if trim then
if value ~= comp then -- value does not equal comp when value contains html markup
local dup2 = duplicate_char;
if dup2:match( "%A" ) then dup2 = "%" .. dup2; end -- if duplicate_char not a letter then escape it
value = value:gsub( "(%b<>)" .. dup2, "%1", 1 ) -- remove duplicate_char if it follows html markup
else
value = value:sub( 2, -1 ); -- remove duplicate_char when it is first character
end
end
end
str = str .. value; --add it to the output string
end
end
return str;
end
--[[--------------------------< S T R I P _ A P O S T R O P H E _ M A R K U P >--------------------------------
Strip wiki italic and bold markup from argument so that it doesn't contaminate COinS metadata.
This function strips common patterns of apostrophe markup. We presume that editors who have taken the time to
markup a title have, as a result, provided valid markup. When they don't, some single apostrophes are left behind.
]]
local function strip_apostrophe_markup (argument)
if not is_set (argument) then return argument; end
while true do
if argument:match ("%'%'%'%'%'") then -- bold italic (5)
argument=argument:gsub("%'%'%'%'%'", ""); -- remove all instances of it
elseif argument:match ("%'%'%'%'") then -- italic start and end without content (4)
argument=argument:gsub("%'%'%'%'", "");
elseif argument:match ("%'%'%'") then -- bold (3)
argument=argument:gsub("%'%'%'", "");
elseif argument:match ("%'%'") then -- italic (2)
argument=argument:gsub("%'%'", "");
else
break;
end
end
return argument; -- done
end
--[[--------------------------< H A S _ I N V I S I B L E _ C H A R S >----------------------------------------
This function searches a parameter's value for nonprintable or invisible characters. The search stops at the
first match.
This function will detect the visible replacement character when it is part of the wikisource.
Detects but ignores nowiki and math stripmarkers. Also detects other named stripmarkers (gallery, math, pre, ref)
and identifies them with a slightly different error message. See also coins_cleanup().
Detects but ignores the character pattern that results from the transclusion of {{'}} templates.
Output of this function is an error message that identifies the character or the Unicode group, or the stripmarker
that was detected along with its position (or, for multi-byte characters, the position of its first byte) in the
parameter value.
]]
local function has_invisible_chars (param, v)
local position = ''; -- position of invisible char or starting position of stripmarker
local dummy; -- end of matching string; not used but required to hold end position when a capture is returned
local capture; -- used by stripmarker detection to hold name of the stripmarker
local i=1;
local stripmarker, apostrophe;
while cfg.invisible_chars[i] do
local char=cfg.invisible_chars[i][1] -- the character or group name
local pattern=cfg.invisible_chars[i][2] -- the pattern used to find it
position, dummy, capture = mw.ustring.find (v, pattern) -- see if the parameter value contains characters that match the pattern
if position then
if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition)
('templatestyles' == capture) then -- templatestyles stripmarker allowed
stripmarker = true; -- set a flag
elseif true == stripmarker and 'delete' == char then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
position = nil; -- unset
elseif 'apostrophe' == char then -- apostrophe template uses ‍, hair space and zero-width space
apostrophe = true;
elseif true == apostrophe and in_array (char, {'zero width joiner', 'zero width space', 'hair space'}) then
position = nil; -- unset
else
local err_msg;
if capture then
err_msg = capture .. ' ' .. cfg.invisible_chars[i][3] or char;
else
err_msg = cfg.invisible_chars[i][3] or (char .. ' character');
end
return {err_msg, wrap_style ('parameter', param), position}; -- and done with this parameter
end
end
i=i+1; -- bump our index
end
end
--[[--------------------------< W R A P _ M S G >--------------------------------------------------------------
Applies additional message text to various parameter values. Supplied string is wrapped using a message_list
configuration taking one argument. Supports lower case text for {{citation}} templates. Additional text taken
from citation_config.messages - the reason this function is similar to but separate from wrap_style().
]]
local function wrap_msg (key, str, lower)
if not is_set (str) then
return '';
elseif in_array (key, cfg.messages['_safe_for_italics']) then
str = safe_for_italics (str);
end
if true == lower then
local msg;
msg = cfg.messages[key]:lower(); -- set the message to lower case before
return substitute (msg, str); -- including template text
else
return substitute (cfg.messages[key], str);
end
end
--[[--------------------------< K E R N _ Q U O T E S >--------------------------------------------------------
Apply kerning to open the space between the quote mark provided by the Module and a leading or trailing quote mark contained in a |title= or |chapter= parameter's value.
This function will positive kern either single or double quotes:
"'Unkerned title with leading and trailing single quote marks'"
" 'Kerned title with leading and trailing single quote marks' " (in real life the kerning isn't as wide as this example)
Double single quotes (italic or bold wikimarkup) are not kerned.
Call this function for chapter titles, for website titles, etc; not for book titles.
]]
local function kern_quotes (str)
local cap='';
local cap2='';
cap, cap2 = str:match ("^([\"\'])([^\'].+)"); -- match leading double or single quote but not double single quotes
if is_set (cap) then
str = wrap_style ('kern-left', {cap, cap2});
end
cap, cap2 = str:match ("^(.+[^\'])([\"\'])$")
if is_set (cap) then
str = wrap_style ('kern-right', {cap, cap2});
end
return str;
end
--[[--------------------------< P E N D _ S E P A R A T O R >--------------------------------------------------
]]
local function pend_separator (item, sepc, prepend)
if prepend then
return is_set (item) and sepc .. ' ' .. item or '';
else
return is_set (item) and item .. sepc .. ' ' or '';
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr)
cfg = cfg_table_ptr;
end
--[[--------------------------< E X P O R T S >----------------------------------------------------------------
]]
return {
first_set = first_set, -- exported functions
has_accept_as_written = has_accept_as_written,
has_invisible_chars = has_invisible_chars,
hyphen_to_dash = hyphen_to_dash,
in_array = in_array,
is_set = is_set,
kern_quotes = kern_quotes,
make_sep_list = make_sep_list,
pend_separator = pend_separator,
safe_join = safe_join,
substitude = substitude,
strip_apostrophe_markup = strip_apostrophe_markup,
substitute = substitute,
wrap_style = wrap_style,
wrap_msg = wrap_msg,
set_selected_modules = set_selected_modules
}
348e3c9fd18b1f4d98186b6f2bce91911d81505b
Template:Hatnote
10
181
369
368
2024-08-04T12:22:01Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Hatnote|hatnote}}</includeonly><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
4a1d1028d07c9056022807a96051e1c82cf2a1c7
Template:Column-width
10
182
371
370
2024-08-04T12:22:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>-moz-column-width: {{{1|30em}}}; -webkit-column-width: {{{1|30em}}}; column-width: {{{1|30em}}};</includeonly><noinclude>
{{documentation}}
</noinclude>
f6fbe6dee4c0e796111386c4d1fe94fcbcd77c7a
Template:Column-count
10
183
373
372
2024-08-04T12:22:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>-moz-column-count: {{{1|2}}}; -webkit-column-count: {{{1|2}}}; column-count: {{{1|2}}};</includeonly><noinclude>
{{documentation}}
</noinclude>
6dc87b32d7baf6ea66fb7b22fa8bc46cf0295095
Template:Language icon
10
184
375
374
2024-08-04T12:22:04Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#ifexist:Template:ISO 639 name {{{1<noinclude>|</noinclude>}}}
|<span style="font-family: sans-serif; cursor: default; color:var(--color-subtle, #54595d); font-size: 0.8em; bottom: 0.1em; font-weight: bold;" title="{{ISO 639 name {{{1}}}}}">({{{2|{{ISO 639 name |{{{1}}}}}}}})</span><!-- {{category handler
|main={{#ifeq:{{{1|}}}|en||[[Category:含有{{ISO 639 name {{{1}}}}}外部連結的條目]]}}
}} -->
|{{error|不正確的語言代碼。}}([[Template:Language_icon|說明]])如果在角色介紹看到此訊息,請參考'''[{{fullurl:夏目友人帳|diff=prev&oldid=34291294}} 這個條目]'''修改原始碼。[[Category:語言標示模板參數錯誤的頁面]]
}}<noinclude>
{{documentation}}
</noinclude>
02eda12992651a026fc38ca646527b54ba5e9928
Template:Notelist
10
185
377
376
2024-08-04T12:22:05Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude><!--
****** 注意 ******
請勿添加任何中文的「註」或「注」功能,
否則會干擾後台對下面幾個保留字的操作,
所有中文功能已遷移至[[Template:noteFoot]]。
--></noinclude><includeonly><div class="notelist" style="list-style-type: {{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = lower-alpha
}};">
{{#tag:references|{{{1|{{{refs|{{{notes|}}}}}}}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group}}}
| #default = lower-alpha
}}}}
</div></includeonly><noinclude>
{{documentation}}
</noinclude>
c3d897b9da64d14bb0ec824c875158105b892281
Template:En icon
10
186
379
378
2024-08-04T12:22:07Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{language icon|en|英文}}<noinclude>{{Documentation}}</noinclude>
70faf378dd9cf75c11eb74120055d9f7e8ffc10c
Module:Documentation
828
97
381
263
2024-08-04T12:22:08Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{documentation}}.
-- Get required modules.
local getArgs = require('Module:Arguments').getArgs
local messageBox = require('Module:Message box')
-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')
local p = {}
-- Often-used functions.
local ugsub = mw.ustring.gsub
----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
--[[
-- Gets a message from the cfg table and formats it if appropriate.
-- The function raises an error if the value from the cfg table is not
-- of the type expectType. The default type for expectType is 'string'.
-- If the table valArray is present, strings such as $1, $2 etc. in the
-- message are substituted with values from the table keys [1], [2] etc.
-- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
-- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
--]]
local msg = cfg[cfgKey]
expectType = expectType or 'string'
if type(msg) ~= expectType then
error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
end
if not valArray then
return msg
end
local function getMessageVal(match)
match = tonumber(match)
return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
end
local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
return ret
end
p.message = message
local function makeWikilink(page, display)
if display then
return mw.ustring.format('[[%s|%s]]', page, display)
else
return mw.ustring.format('[[%s]]', page)
end
end
p.makeWikilink = makeWikilink
local function makeCategoryLink(cat, sort)
local catns = mw.site.namespaces[14].name
return makeWikilink(catns .. ':' .. cat, sort)
end
p.makeCategoryLink = makeCategoryLink
local function makeUrlLink(url, display)
return mw.ustring.format('[%s %s]', url, display)
end
p.makeUrlLink = makeUrlLink
local function makeToolbar(...)
local ret = {}
local lim = select('#', ...)
if lim < 1 then
return nil
end
for i = 1, lim do
ret[#ret + 1] = select(i, ...)
end
return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
end
p.makeToolbar = makeToolbar
----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local args = getArgs(frame, {
valueFunc = function (key, value)
if type(value) == 'string' then
value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
if key == 'heading' or value ~= '' then
return value
else
return nil
end
else
return value
end
end
})
return p[funcName](args)
end
end
----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
if mw.title.getCurrentTitle().subpageText == 'testcases' then
return frame:expandTemplate{title = 'module test cases notice'}
else
return p.main(frame)
end
end
----------------------------------------------------------------------------
-- Main function
----------------------------------------------------------------------------
p.main = makeInvokeFunc('_main')
function p._main(args)
--[[
-- This function defines logic flow for the module.
-- @args - table of arguments passed by the user
--
-- Messages:
-- 'main-div-id' --> 'template-documentation'
-- 'main-div-classes' --> 'template-documentation iezoomfix'
--]]
local env = p.getEnvironment(args)
local root = mw.html.create()
root
:wikitext(p._getModuleWikitext(args, env))
:wikitext(p.protectionTemplate(env))
:wikitext(p.sandboxNotice(args, env))
-- This div tag is from {{documentation/start box}}, but moving it here
-- so that we don't have to worry about unclosed tags.
:tag('div')
:attr('id', message('main-div-id'))
:addClass(message('main-div-classes'))
:newline()
:wikitext(p._startBox(args, env))
:wikitext(p._content(args, env))
:tag('div')
:css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
:newline()
:done()
:done()
:wikitext(p._endBox(args, env))
:wikitext(p.addTrackingCategories(env))
return tostring(root)
end
----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
--[[
-- Returns a table with information about the environment, including title objects and other namespace- or
-- path-related data.
-- @args - table of arguments passed by the user
--
-- Title objects include:
-- env.title - the page we are making documentation for (usually the current title)
-- env.templateTitle - the template (or module, file, etc.)
-- env.docTitle - the /doc subpage.
-- env.sandboxTitle - the /sandbox subpage.
-- env.testcasesTitle - the /testcases subpage.
-- env.printTitle - the print version of the template, located at the /Print subpage.
--
-- Data includes:
-- env.protectionLevels - the protection levels table of the title object.
-- env.subjectSpace - the number of the title's subject namespace.
-- env.docSpace - the number of the namespace the title puts its documentation in.
-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
--
-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
-- returned will be nil.
--]]
local env, envFuncs = {}, {}
-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
-- returned by that function is memoized in the env table so that we don't call any of the functions
-- more than once. (Nils won't be memoized.)
setmetatable(env, {
__index = function (t, key)
local envFunc = envFuncs[key]
if envFunc then
local success, val = pcall(envFunc)
if success then
env[key] = val -- Memoise the value.
return val
end
end
return nil
end
})
function envFuncs.title()
-- The title object for the current page, or a test page passed with args.page.
local title
local titleArg = args.page
if titleArg then
title = mw.title.new(titleArg)
else
title = mw.title.getCurrentTitle()
end
return title
end
function envFuncs.templateTitle()
--[[
-- The template (or module, etc.) title object.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
-- 'testcases-subpage' --> 'testcases'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local subpage = title.subpageText
if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
return mw.title.makeTitle(subjectSpace, title.baseText)
else
return mw.title.makeTitle(subjectSpace, title.text)
end
end
function envFuncs.docTitle()
--[[
-- Title object of the /doc subpage.
-- Messages:
-- 'doc-subpage' --> 'doc'
--]]
local title = env.title
local docname = args[1] -- User-specified doc page.
local docpage
if docname then
docpage = docname
else
docpage = env.docpageBase .. '/' .. message('doc-subpage')
end
return mw.title.new(docpage)
end
function envFuncs.sandboxTitle()
--[[
-- Title object for the /sandbox subpage.
-- Messages:
-- 'sandbox-subpage' --> 'sandbox'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
end
function envFuncs.testcasesTitle()
--[[
-- Title object for the /testcases subpage.
-- Messages:
-- 'testcases-subpage' --> 'testcases'
--]]
return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
end
function envFuncs.printTitle()
--[[
-- Title object for the /Print subpage.
-- Messages:
-- 'print-subpage' --> 'Print'
--]]
return env.templateTitle:subPageTitle(message('print-subpage'))
end
function envFuncs.protectionLevels()
-- The protection levels table of the title object.
return env.title.protectionLevels
end
function envFuncs.subjectSpace()
-- The subject namespace number.
return mw.site.namespaces[env.title.namespace].subject.id
end
function envFuncs.docSpace()
-- The documentation namespace number. For most namespaces this is the same as the
-- subject namespace. However, pages in the Article, File, MediaWiki or Category
-- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
local subjectSpace = env.subjectSpace
if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
return subjectSpace + 1
else
return subjectSpace
end
end
function envFuncs.docpageBase()
-- The base page of the /doc, /sandbox, and /testcases subpages.
-- For some namespaces this is the talk page, rather than the template page.
local templateTitle = env.templateTitle
local docSpace = env.docSpace
local docSpaceText = mw.site.namespaces[docSpace].name
-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
return docSpaceText .. ':' .. templateTitle.text
end
function envFuncs.compareUrl()
-- Diff link between the sandbox and the main template using [[Special:ComparePages]].
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
if templateTitle.exists and sandboxTitle.exists then
local compareUrl = mw.uri.fullUrl(
'Special:ComparePages',
{page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
)
return tostring(compareUrl)
else
return nil
end
end
return env
end
----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')
function p._getModuleWikitext(args, env)
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.contentModel ~= 'Scribunto' then return end
pcall(require, currentTitle.prefixedText) -- if it fails, we don't care
local moduleWikitext = package.loaded["Module:Module wikitext"]
if moduleWikitext then
return moduleWikitext.main()
end
return ''
end
function p.sandboxNotice(args, env)
--[=[
-- Generates a sandbox notice for display above sandbox pages.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
-- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
-- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
-- 'sandbox-notice-pagetype-template' --> '[[那艺娜维基:Template test cases|template sandbox]] page'
-- 'sandbox-notice-pagetype-module' --> '[[那艺娜维基:Template test cases|module sandbox]] page'
-- 'sandbox-notice-pagetype-other' --> 'sandbox page'
-- 'sandbox-notice-compare-link-display' --> 'diff'
-- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
-- 'sandbox-notice-testcases-link-display' --> 'test cases'
-- 'sandbox-category' --> 'Template sandboxes'
--]=]
local title = env.title
local sandboxTitle = env.sandboxTitle
local templateTitle = env.templateTitle
local subjectSpace = env.subjectSpace
if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
return nil
end
-- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
local omargs = {}
omargs.image = message('sandbox-notice-image')
-- Get the text. We start with the opening blurb, which is something like
-- "This is the template sandbox for [[Template:Foo]] (diff)."
local text = ''
local pagetype
if subjectSpace == 10 then
pagetype = message('sandbox-notice-pagetype-template')
elseif subjectSpace == 828 then
pagetype = message('sandbox-notice-pagetype-module')
else
pagetype = message('sandbox-notice-pagetype-other')
end
local pagetypee
if subjectSpace == 10 then
pagetypee = message('template-pagetype')
elseif subjectSpace == 828 then
pagetypee = message('module-pagetype')
else
pagetypee = message('default-pagetype')--message 'other-pagetype' 不存在
end
local templateLink = makeWikilink(templateTitle.prefixedText)
local compareUrl = env.compareUrl
if compareUrl then
local compareDisplay = message('sandbox-notice-compare-link-display')
local compareLink = makeUrlLink(compareUrl, compareDisplay)
text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
else
text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
end
-- Get the test cases page blurb if the page exists. This is something like
-- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
local testcasesTitle = env.testcasesTitle
if testcasesTitle and testcasesTitle.exists then
if testcasesTitle.namespace == mw.site.namespaces.Module.id then
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-run-blurb', {pagetypee, testcasesLink, testcasesRunLink}) .. '</small>'
else
local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
text = text .. '<br /><small>' .. message('sandbox-notice-testcases-blurb', {pagetypee, testcasesLink}) .. '</small>'
end
end
-- Add the sandbox to the sandbox category.
text = text .. makeCategoryLink(message('sandbox-category'))
omargs.text = text
local ret = '<div style="clear: both;"></div>'
ret = ret .. messageBox.main('ombox', omargs)
return ret
end
function p.protectionTemplate(env)
-- Generates the padlock icon in the top right.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'protection-template' --> 'pp-template'
-- 'protection-template-args' --> {docusage = 'yes'}
local protectionLevels, mProtectionBanner
local title = env.title
protectionLevels = env.protectionLevels
if not protectionLevels then
return nil
end
local editProt = protectionLevels.edit and protectionLevels.edit[1]
local moveProt = protectionLevels.move and protectionLevels.move[1]
if editProt then
-- The page is edit-protected.
mProtectionBanner = require('Module:Protection banner')
local reason = message('protection-reason-edit')
return mProtectionBanner._main{reason, small = true}
elseif moveProt and moveProt ~= 'autoconfirmed' then
-- The page is move-protected but not edit-protected. Exclude move
-- protection with the level "autoconfirmed", as this is equivalent to
-- no move protection at all.
mProtectionBanner = require('Module:Protection banner')
return mProtectionBanner._main{action = 'move', small = true}
else
return nil
end
end
----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')
function p._startBox(args, env)
--[[
-- This function generates the start box.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
-- which generate the box HTML.
--]]
env = env or p.getEnvironment(args)
local links
local content = args.content
if not content then
-- No need to include the links if the documentation is on the template page itself.
local linksData = p.makeStartBoxLinksData(args, env)
if linksData then
links = p.renderStartBoxLinks(linksData)
end
end
-- Generate the start box html.
local data = p.makeStartBoxData(args, env, links)
if data then
return p.renderStartBox(data)
else
-- User specified no heading.
return nil
end
end
function p.makeStartBoxLinksData(args, env)
--[[
-- Does initial processing of data to make the [view] [edit] [history] [purge] links.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'view-link-display' --> 'view'
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'purge-link-display' --> 'purge'
-- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'docpage-preload' --> 'Template:Documentation/preload'
-- 'create-link-display' --> 'create'
--]]
local subjectSpace = env.subjectSpace
local title = env.title
local docTitle = env.docTitle
if not title or not docTitle then
return nil
end
local data = {}
data.title = title
data.docTitle = docTitle
-- View, display, edit, and purge links if /doc exists.
data.viewLinkDisplay = message('view-link-display')
data.editLinkDisplay = message('edit-link-display')
data.historyLinkDisplay = message('history-link-display')
data.purgeLinkDisplay = message('purge-link-display')
-- Create link if /doc doesn't exist.
local preload = args.preload
if not preload then
if subjectSpace == 6 then -- File namespace
preload = message('file-docpage-preload')
elseif subjectSpace == 828 then -- Module namespace
preload = message('module-preload')
else
preload = message('docpage-preload')
end
end
data.preload = preload
data.createLinkDisplay = message('create-link-display')
return data
end
function p.renderStartBoxLinks(data)
--[[
-- Generates the [view][edit][history][purge] or [create] links from the data table.
-- @data - a table of data generated by p.makeStartBoxLinksData
--]]
local function escapeBrackets(s)
-- Escapes square brackets with HTML entities.
s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
s = s:gsub('%]', ']')
return s
end
local ret
local docTitle = data.docTitle
local title = data.title
if docTitle.exists then
local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
ret = '[%s] [%s] [%s] [%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
else
local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
ret = '[%s]'
ret = escapeBrackets(ret)
ret = mw.ustring.format(ret, createLink)
end
return ret
end
function p.makeStartBoxData(args, env, links)
--[=[
-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
--
-- Messages:
-- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
-- 'template-namespace-heading' --> 'Template documentation'
-- 'module-namespace-heading' --> 'Module documentation'
-- 'file-namespace-heading' --> 'Summary'
-- 'other-namespaces-heading' --> 'Documentation'
-- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
-- 'start-box-link-id' --> 'doc_editlinks'
-- 'testcases-create-link-display' --> 'create'
--]=]
local subjectSpace = env.subjectSpace
if not subjectSpace then
-- Default to an "other namespaces" namespace, so that we get at least some output
-- if an error occurs.
subjectSpace = 2
end
local data = {}
-- Heading
local heading = args.heading -- Blank values are not removed.
if heading == '' then
-- Don't display the start box if the heading arg is defined but blank.
return nil
end
if heading then
data.heading = heading
elseif subjectSpace == 10 then -- Template namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
elseif subjectSpace == 828 then -- Module namespace
data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
elseif subjectSpace == 6 then -- File namespace
data.heading = message('file-namespace-heading')
else
data.heading = message('other-namespaces-heading')
end
-- Heading CSS
local headingStyle = args['heading-style']
if headingStyle then
data.headingStyleText = headingStyle
elseif subjectSpace == 10 then
-- We are in the template or template talk namespaces.
data.headingFontWeight = 'bold'
data.headingFontSize = '125%'
else
data.headingFontSize = '150%'
end
-- Data for the [view][edit][history][purge] or [create] links.
if links then
data.linksClass = message('start-box-linkclasses')
data.linksId = message('start-box-link-id')
data.links = links
end
return data
end
function p.renderStartBox(data)
-- Renders the start box html.
-- @data - a table of data generated by p.makeStartBoxData.
local sbox = mw.html.create('div')
sbox
:css('padding-bottom', '3px')
:css('border-bottom', '1px solid #aaa')
:css('margin-bottom', '1ex')
:newline()
:tag('span')
:cssText(data.headingStyleText)
:css('font-weight', data.headingFontWeight)
:css('font-size', data.headingFontSize)
:wikitext(data.heading)
local links = data.links
if links then
sbox:tag('span')
:addClass(data.linksClass)
:attr('id', data.linksId)
:wikitext(links)
end
return tostring(sbox)
end
----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')
function p._content(args, env)
-- Displays the documentation contents
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
local content = args.content
if not content and docTitle and docTitle.exists then
content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
end
-- The line breaks below are necessary so that "=== Headings ===" at the start and end
-- of docs are interpreted correctly.
return '\n' .. (content or '') .. '\n'
end
p.contentTitle = makeInvokeFunc('_contentTitle')
function p._contentTitle(args, env)
env = env or p.getEnvironment(args)
local docTitle = env.docTitle
if not args.content and docTitle and docTitle.exists then
return docTitle.prefixedText
else
return ''
end
end
----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')
function p._endBox(args, env)
--[=[
-- This function generates the end box (also known as the link box).
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'fmbox-id' --> 'documentation-meta-data'
-- 'fmbox-style' --> 'background-color: #ecfcf4'
-- 'fmbox-textstyle' --> 'font-style: italic'
--
-- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
--]=]
-- Get environment data.
env = env or p.getEnvironment(args)
local subjectSpace = env.subjectSpace
local docTitle = env.docTitle
if not subjectSpace or not docTitle then
return nil
end
-- Check whether we should output the end box at all. Add the end
-- box by default if the documentation exists or if we are in the
-- user, module or template namespaces.
local linkBox = args['link box']
if linkBox == 'off'
or not (
docTitle.exists
or subjectSpace == 2
or subjectSpace == 828
or subjectSpace == 10
)
then
return nil
end
-- Assemble the arguments for {{fmbox}}.
local fmargs = {}
fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
fmargs.image = 'none'
fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
-- Assemble the fmbox text field.
local text = ''
if linkBox then
text = text .. linkBox
else
text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
-- We are in the user, template or module namespaces.
-- Add sandbox and testcases links.
-- "Editors can experiment in this template's sandbox and testcases pages."
text = text .. (p.makeExperimentBlurb(args, env) or '')
text = text .. '<br />'
if not args.content and not args[1] then
-- "Please add categories to the /doc subpage."
-- Don't show this message with inline docs or with an explicitly specified doc page,
-- as then it is unclear where to add the categories.
text = text .. (p.makeCategoriesBlurb(args, env) or '')
end
text = text .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
if printBlurb then
text = text .. '<br />' .. printBlurb
end
end
end
fmargs.text = text
return messageBox.main('fmbox', fmargs)
end
function p.makeDocPageBlurb(args, env)
--[=[
-- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'edit-link-display' --> 'edit'
-- 'history-link-display' --> 'history'
-- 'transcluded-from-blurb' -->
-- 'The above [[那艺娜维基:Template documentation|documentation]]
-- is [[那艺娜维基:Transclusion|transcluded]] from $1.'
-- 'module-preload' --> 'Template:Documentation/preload-module-doc'
-- 'create-link-display' --> 'create'
-- 'create-module-doc-blurb' -->
-- 'You might want to $1 a documentation page for this [[那艺娜维基:Lua|Scribunto module]].'
--]=]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local ret
if docTitle.exists then
-- /doc exists; link to it.
local docLink = makeWikilink(docTitle.prefixedText)
local editUrl = docTitle:fullUrl{action = 'edit'}
local editDisplay = message('edit-link-display')
local editLink = makeUrlLink(editUrl, editDisplay)
local historyUrl = docTitle:fullUrl{action = 'history'}
local historyDisplay = message('history-link-display')
local historyLink = makeUrlLink(historyUrl, historyDisplay)
ret = message('transcluded-from-blurb', {docLink})
.. ' '
.. makeToolbar(editLink, historyLink)
.. '<br />'
elseif env.subjectSpace == 828 then
-- /doc does not exist; ask to create it.
local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
local createDisplay = message('create-link-display')
local createLink = makeUrlLink(createUrl, createDisplay)
ret = message('create-module-doc-blurb', {createLink})
.. '<br />'
end
return ret
end
function p.makeExperimentBlurb(args, env)
--[[
-- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'sandbox-link-display' --> 'sandbox'
-- 'sandbox-edit-link-display' --> 'edit'
-- 'compare-link-display' --> 'diff'
-- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'sandbox-create-link-display' --> 'create'
-- 'mirror-edit-summary' --> 'Create sandbox version of $1'
-- 'mirror-link-display' --> 'mirror'
-- 'mirror-link-preload' --> 'Template:Documentation/mirror'
-- 'sandbox-link-display' --> 'sandbox'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display'--> 'edit'
-- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
-- 'testcases-create-link-display' --> 'create'
-- 'testcases-link-display' --> 'testcases'
-- 'testcases-edit-link-display' --> 'edit'
-- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
-- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
-- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
-- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
local sandboxTitle = env.sandboxTitle
local testcasesTitle = env.testcasesTitle
local templatePage = templateTitle.prefixedText
if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
return nil
end
-- Make links.
local sandboxLinks, testcasesLinks
if sandboxTitle.exists then
local sandboxPage = sandboxTitle.prefixedText
local sandboxDisplay = message('sandbox-link-display')
local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
local sandboxEditDisplay = message('sandbox-edit-link-display')
local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
local compareUrl = env.compareUrl
local compareLink
if compareUrl then
local compareDisplay = message('compare-link-display')
compareLink = makeUrlLink(compareUrl, compareDisplay)
end
sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
else
local sandboxPreload
if subjectSpace == 828 then
sandboxPreload = message('module-sandbox-preload')
else
sandboxPreload = message('template-sandbox-preload')
end
local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
local sandboxCreateDisplay = message('sandbox-create-link-display')
local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
local mirrorPreload = message('mirror-link-preload')
local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
if subjectSpace == 828 then
mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
end
local mirrorDisplay = message('mirror-link-display')
local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
end
if testcasesTitle.exists then
local testcasesPage = testcasesTitle.prefixedText
local testcasesDisplay = message('testcases-link-display')
local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
local testcasesEditDisplay = message('testcases-edit-link-display')
local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
-- for Modules, add testcases run link if exists
if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
local testcasesRunLinkDisplay = message('testcases-run-link-display')
local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
else
testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
end
else
local testcasesPreload
if subjectSpace == 828 then
testcasesPreload = message('module-testcases-preload')
else
testcasesPreload = message('template-testcases-preload')
end
local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
local testcasesCreateDisplay = message('testcases-create-link-display')
local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
end
local messageName
if subjectSpace == 828 then
messageName = 'experiment-blurb-module'
else
messageName = 'experiment-blurb-template'
end
return message(messageName, {sandboxLinks, testcasesLinks})
end
function p.makeCategoriesBlurb(args, env)
--[[
-- Generates the text "Please add categories to the /doc subpage."
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'doc-link-display' --> '/doc'
-- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
--]]
local docTitle = env.docTitle
if not docTitle then
return nil
end
local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
return message('add-categories-blurb', {docPathLink})
end
function p.makeSubpagesBlurb(args, env)
--[[
-- Generates the "Subpages of this template" link.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'template-pagetype' --> 'template'
-- 'module-pagetype' --> 'module'
-- 'default-pagetype' --> 'page'
-- 'subpages-link-display' --> 'Subpages of this $1'
--]]
local subjectSpace = env.subjectSpace
local templateTitle = env.templateTitle
if not subjectSpace or not templateTitle then
return nil
end
local pagetype
if subjectSpace == 10 then
pagetype = message('template-pagetype')
elseif subjectSpace == 828 then
pagetype = message('module-pagetype')
else
pagetype = message('default-pagetype')
end
local subpagesLink = makeWikilink(
'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
message('subpages-link-display', {pagetype})
)
return message('subpages-blurb', {subpagesLink})
end
function p.makePrintBlurb(args, env)
--[=[
-- Generates the blurb displayed when there is a print version of the template available.
-- @args - a table of arguments passed by the user
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
--
-- Messages:
-- 'print-link-display' --> '/Print'
-- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
-- .. ' of this template exists at $1.'
-- .. ' If you make a change to this template, please update the print version as well.'
-- 'display-print-category' --> true
-- 'print-category' --> 'Templates with print versions'
--]=]
local printTitle = env.printTitle
if not printTitle then
return nil
end
local ret
if printTitle.exists then
local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
ret = message('print-blurb', {printLink})
local displayPrintCategory = message('display-print-category', nil, 'boolean')
if displayPrintCategory then
ret = ret .. makeCategoryLink(message('print-category'))
end
end
return ret
end
----------------------------------------------------------------------------
-- Tracking categories
----------------------------------------------------------------------------
function p.addTrackingCategories(env)
--[[
-- Check if {{documentation}} is transcluded on a /doc or /testcases page.
-- @env - environment table containing title objects, etc., generated with p.getEnvironment
-- Messages:
-- 'display-strange-usage-category' --> true
-- 'doc-subpage' --> 'doc'
-- 'testcases-subpage' --> 'testcases'
-- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
--
-- /testcases pages in the module namespace are not categorised, as they may have
-- {{documentation}} transcluded automatically.
--]]
local title = env.title
local subjectSpace = env.subjectSpace
if not title or not subjectSpace then
return nil
end
local subpage = title.subpageText
local ret = ''
if message('display-strange-usage-category', nil, 'boolean')
and (
subpage == message('doc-subpage')
or subjectSpace ~= 828 and subpage == message('testcases-subpage')
)
then
ret = ret .. makeCategoryLink(message('strange-usage-category'))
end
return ret
end
return p
2c374c042ebd8bc4d2d63d207aa078459069c065
Module:Documentation/config
828
98
383
265
2024-08-04T12:22:08Z
黑茶
2
导入1个版本
Scribunto
text/plain
----------------------------------------------------------------------------------------------------
--
-- Configuration for Module:Documentation
--
-- Here you can set the values of the parameters and messages used in Module:Documentation to
-- localise it to your wiki and your language. Unless specified otherwise, values given here
-- should be string values.
----------------------------------------------------------------------------------------------------
local cfg = {} -- Do not edit this line.
----------------------------------------------------------------------------------------------------
-- Protection template configuration
----------------------------------------------------------------------------------------------------
-- cfg['protection-reason-edit']
-- The protection reason for edit-protected templates to pass to
-- [[Module:Protection banner]].
cfg['protection-reason-edit'] = 'template'
--[[
----------------------------------------------------------------------------------------------------
-- Sandbox notice configuration
--
-- On sandbox pages the module can display a template notifying users that the current page is a
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a
-- sandbox or not based on the value of cfg['sandbox-subpage']. The following settings configure the
-- messages that the notices contains.
----------------------------------------------------------------------------------------------------
--]]
-- cfg['sandbox-notice-image']
-- The image displayed in the sandbox notice.
cfg['sandbox-notice-image'] = '[[Image:Sandbox.svg|50px|alt=|link=]]'
--[[
-- cfg['sandbox-notice-pagetype-template']
-- cfg['sandbox-notice-pagetype-module']
-- cfg['sandbox-notice-pagetype-other']
-- The page type of the sandbox page. The message that is displayed depends on the current subject
-- namespace. This message is used in either cfg['sandbox-notice-blurb'] or
-- cfg['sandbox-notice-diff-blurb'].
--]]
cfg['sandbox-notice-pagetype-template'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-module'] = '[[那艺娜维基:模板的沙盒和测试样例|沙盒]]'
cfg['sandbox-notice-pagetype-other'] = '沙盒'
--[[
-- cfg['sandbox-notice-blurb']
-- cfg['sandbox-notice-diff-blurb']
-- cfg['sandbox-notice-diff-display']
-- Either cfg['sandbox-notice-blurb'] or cfg['sandbox-notice-diff-blurb'] is the opening sentence
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page
-- type, which is either cfg['sandbox-notice-pagetype-template'],
-- cfg['sandbox-notice-pagetype-module'] or cfg['sandbox-notice-pagetype-other'] depending what
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between
-- the sandbox and the main template. The display value of the diff link is set by
-- cfg['sandbox-notice-compare-link-display'].
--]]
cfg['sandbox-notice-blurb'] = '这是$2的$1。'
cfg['sandbox-notice-diff-blurb'] = '这是$2($3)的$1。'
cfg['sandbox-notice-compare-link-display'] = '差异'
--[[
-- cfg['sandbox-notice-testcases-blurb']
-- cfg['sandbox-notice-testcases-link-display']
-- cfg['sandbox-notice-testcases-run-blurb']
-- cfg['sandbox-notice-testcases-run-link-display']
-- cfg['sandbox-notice-testcases-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.
-- cfg['sandbox-notice-testcases-link-display'] is the display value for that link.
-- cfg['sandbox-notice-testcases-run-blurb'] is a sentence notifying the user that there is a test cases page
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test
-- cases page, and $2 is a link to the page to run it.
-- cfg['sandbox-notice-testcases-run-link-display'] is the display value for the link to run the test
-- cases.
--]]
cfg['sandbox-notice-testcases-blurb'] = '参见本$1的$2。'
cfg['sandbox-notice-testcases-link-display'] = '测试样例'
cfg['sandbox-notice-testcases-run-blurb'] = '参见本$1的$2($3)。'
cfg['sandbox-notice-testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['sandbox-category']
-- A category to add to all template sandboxes.
cfg['sandbox-category'] = '模板沙盒'
----------------------------------------------------------------------------------------------------
-- Start box configuration
----------------------------------------------------------------------------------------------------
-- cfg['documentation-icon-wikitext']
-- The wikitext for the icon shown at the top of the template.
cfg['documentation-icon-wikitext'] = '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=-{zh-cn:文档; zh-tw:文件;}-图示]]'
-- cfg['template-namespace-heading']
-- The heading shown in the template namespace.
cfg['template-namespace-heading'] = '模板-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['module-namespace-heading']
-- The heading shown in the module namespace.
cfg['module-namespace-heading'] = '-{zh-hans:模块;zh-hant:模組}--{zh-cn:文档; zh-tw:文件;}-'
-- cfg['file-namespace-heading']
-- The heading shown in the file namespace.
cfg['file-namespace-heading'] = 'Summary'
-- cfg['other-namespaces-heading']
-- The heading shown in other namespaces.
cfg['other-namespaces-heading'] = '-{zh-cn:文档; zh-tw:文件;}-'
-- cfg['view-link-display']
-- The text to display for "view" links.
cfg['view-link-display'] = '-{zh-cn:查看;zh-tw:檢視}-'
-- cfg['edit-link-display']
-- The text to display for "edit" links.
cfg['edit-link-display'] = '编辑'
-- cfg['history-link-display']
-- The text to display for "history" links.
cfg['history-link-display'] = '历史'
-- cfg['purge-link-display']
-- The text to display for "purge" links.
cfg['purge-link-display'] = '清除-{zh-hans:缓存;zh-hant:快取}-'
-- cfg['create-link-display']
-- The text to display for "create" links.
cfg['create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Link box (end box) configuration
----------------------------------------------------------------------------------------------------
-- cfg['transcluded-from-blurb']
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.
cfg['transcluded-from-blurb'] = '上述[[那艺娜维基:模板文檔頁模式|-{zh-cn:文档; zh-tw:文件;}-]][[那艺娜维基:嵌入包含|嵌入]]自$1。'
--[[
-- cfg['create-module-doc-blurb']
-- Notice displayed in the module namespace when the documentation subpage does not exist.
-- $1 is a link to create the documentation page with the preload cfg['module-preload'] and the
-- display cfg['create-link-display'].
--]]
cfg['create-module-doc-blurb'] = '您可能想要$1本[[那艺娜维基:Lua|Scribunto-{zh-hans:模块;zh-hant:模組}-]]的-{zh-cn:文档; zh-tw:文件;}-。'
----------------------------------------------------------------------------------------------------
-- Experiment blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['experiment-blurb-template']
-- cfg['experiment-blurb-module']
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.
-- It is only shown in the template and module namespaces. With the default English settings, it
-- might look like this:
--
-- Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages.
--
-- In this example, "sandbox", "edit", "diff", "testcases", and "edit" would all be links.
--
-- There are two versions, cfg['experiment-blurb-template'] and cfg['experiment-blurb-module'], depending
-- on what namespace we are in.
--
-- Parameters:
--
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-edit-link-display'] | cfg['compare-link-display'])
--
-- If the sandbox doesn't exist, it is in the format:
--
-- cfg['sandbox-link-display'](cfg['sandbox-create-link-display'] | cfg['mirror-link-display'])
--
-- The link for cfg['sandbox-create-link-display'] link preloads the page with cfg['template-sandbox-preload']
-- or cfg['module-sandbox-preload'], depending on the current namespace. The link for cfg['mirror-link-display']
-- loads a default edit summary of cfg['mirror-edit-summary'].
--
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:
--
-- cfg['testcases-link-display'](cfg['testcases-edit-link-display'])
--
-- If the test cases page doesn't exist, it is in the format:
--
-- cfg['testcases-link-display'](cfg['testcases-create-link-display'])
--
-- If the test cases page doesn't exist, the link for cfg['testcases-create-link-display'] preloads the
-- page with cfg['template-testcases-preload'] or cfg['module-testcases-preload'], depending on the current
-- namespace.
--]]
cfg['experiment-blurb-template'] = "编者可以在本模板的$1和$2页面进行实验。"
cfg['experiment-blurb-module'] = "编者可以在本-{zh-cn:模块; zh-tw:模組}-的$1和$2页面进行实验。"
----------------------------------------------------------------------------------------------------
-- Sandbox link configuration
----------------------------------------------------------------------------------------------------
-- cfg['sandbox-subpage']
-- The name of the template subpage typically used for sandboxes.
cfg['sandbox-subpage'] = 'sandbox'
-- cfg['template-sandbox-preload']
-- Preload file for template sandbox pages.
cfg['template-sandbox-preload'] = 'Template:Documentation/preload-sandbox'
-- cfg['module-sandbox-preload']
-- Preload file for Lua module sandbox pages.
cfg['module-sandbox-preload'] = 'Template:Documentation/preload-module-sandbox'
-- cfg['sandbox-link-display']
-- The text to display for "sandbox" links.
cfg['sandbox-link-display'] = '沙盒'
-- cfg['sandbox-edit-link-display']
-- The text to display for sandbox "edit" links.
cfg['sandbox-edit-link-display'] = '编辑'
-- cfg['sandbox-create-link-display']
-- The text to display for sandbox "create" links.
cfg['sandbox-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
-- cfg['compare-link-display']
-- The text to display for "compare" links.
cfg['compare-link-display'] = '差异'
-- cfg['mirror-edit-summary']
-- The default edit summary to use when a user clicks the "mirror" link. $1 is a wikilink to the
-- template page.
cfg['mirror-edit-summary'] = '建立$1的沙盒版本' -- 本訊息無法使用轉換
-- cfg['mirror-link-display']
-- The text to display for "mirror" links.
cfg['mirror-link-display'] = '镜像'
-- cfg['mirror-link-preload']
-- The page to preload when a user clicks the "mirror" link.
cfg['mirror-link-preload'] = 'Template:Documentation/mirror'
----------------------------------------------------------------------------------------------------
-- Test cases link configuration
----------------------------------------------------------------------------------------------------
-- cfg['testcases-subpage']
-- The name of the template subpage typically used for test cases.
cfg['testcases-subpage'] = 'testcases'
-- cfg['template-testcases-preload']
-- Preload file for template test cases pages.
cfg['template-testcases-preload'] = 'Template:Documentation/preload-testcases'
-- cfg['module-testcases-preload']
-- Preload file for Lua module test cases pages.
cfg['module-testcases-preload'] = 'Template:Documentation/preload-module-testcases'
-- cfg['testcases-link-display']
-- The text to display for "testcases" links.
cfg['testcases-link-display'] = '测试样例'
-- cfg['testcases-edit-link-display']
-- The text to display for test cases "edit" links.
cfg['testcases-edit-link-display'] = '编辑'
-- cfg['testcases-run-link-display']
-- The text to display for test cases "run" links.
cfg['testcases-run-link-display'] = '-{zh-cn:运行; zh-tw:執行;}-'
-- cfg['testcases-create-link-display']
-- The text to display for test cases "create" links.
cfg['testcases-create-link-display'] = '-{zh-cn:创建; zh-tw:建立;}-'
----------------------------------------------------------------------------------------------------
-- Add categories blurb configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['add-categories-blurb']
-- Text to direct users to add categories to the /doc subpage. Not used if the "content" or
-- "docname fed" arguments are set, as then it is not clear where to add the categories. $1 is a
-- link to the /doc subpage with a display value of cfg['doc-link-display'].
--]]
cfg['add-categories-blurb'] = '请在$1子页面中添加分类。'
-- cfg['doc-link-display']
-- The text to display when linking to the /doc subpage.
cfg['doc-link-display'] = '/doc'
----------------------------------------------------------------------------------------------------
-- Subpages link configuration
----------------------------------------------------------------------------------------------------
--[[
-- cfg['subpages-blurb']
-- The "Subpages of this template" blurb. $1 is a link to the main template's subpages with a
-- display value of cfg['subpages-link-display']. In the English version this blurb is simply
-- the link followed by a period, and the link display provides the actual text.
--]]
cfg['subpages-blurb'] = '$1。'
--[[
-- cfg['subpages-link-display']
-- The text to display for the "subpages of this page" link. $1 is cfg['template-pagetype'],
-- cfg['module-pagetype'] or cfg['default-pagetype'], depending on whether the current page is in
-- the template namespace, the module namespace, or another namespace.
--]]
cfg['subpages-link-display'] = '本$1的子页面'
-- cfg['template-pagetype']
-- The pagetype to display for template pages.
cfg['template-pagetype'] = '模板'
-- cfg['module-pagetype']
-- The pagetype to display for Lua module pages.
cfg['module-pagetype'] = '-{zh-cn:模块; zh-tw:模組;}-'
-- cfg['default-pagetype']
-- The pagetype to display for pages other than templates or Lua modules.
cfg['default-pagetype'] = '页'
----------------------------------------------------------------------------------------------------
-- Doc link configuration
----------------------------------------------------------------------------------------------------
-- cfg['doc-subpage']
-- The name of the subpage typically used for documentation pages.
cfg['doc-subpage'] = 'doc'
-- cfg['file-docpage-preload']
-- Preload file for documentation page in the file namespace.
cfg['file-docpage-preload'] = 'Template:Documentation/preload-filespace'
-- cfg['docpage-preload']
-- Preload file for template documentation pages in all namespaces.
cfg['docpage-preload'] = 'Template:Documentation/preload'
-- cfg['module-preload']
-- Preload file for Lua module documentation pages.
cfg['module-preload'] = 'Template:Documentation/preload-module-doc'
----------------------------------------------------------------------------------------------------
-- Print version configuration
----------------------------------------------------------------------------------------------------
-- cfg['print-subpage']
-- The name of the template subpage used for print versions.
cfg['print-subpage'] = 'Print'
-- cfg['print-link-display']
-- The text to display when linking to the /Print subpage.
cfg['print-link-display'] = '/Print'
-- cfg['print-blurb']
-- Text to display if a /Print subpage exists. $1 is a link to the subpage with a display value of cfg['print-link-display'].
cfg['print-blurb'] = 'A [[Help:Books/for experts#Improving the book layout|print version]] of this template exists at $1.'
.. ' If you make a change to this template, please update the print version as well.'
-- cfg['display-print-category']
-- Set to true to enable output of cfg['print-category'] if a /Print subpage exists.
-- This should be a boolean value (either true or false).
cfg['display-print-category'] = true
-- cfg['print-category']
-- Category to output if cfg['display-print-category'] is set to true, and a /Print subpage exists.
cfg['print-category'] = 'Templates with print versions'
----------------------------------------------------------------------------------------------------
-- HTML and CSS configuration
----------------------------------------------------------------------------------------------------
-- cfg['main-div-id']
-- The "id" attribute of the main HTML "div" tag.
cfg['main-div-id'] = 'template-documentation'
-- cfg['main-div-classes']
-- The CSS classes added to the main HTML "div" tag.
cfg['main-div-classes'] = 'template-documentation iezoomfix'
-- cfg['start-box-linkclasses']
-- The CSS classes used for the [view][edit][history] or [create] links in the start box.
cfg['start-box-linkclasses'] = 'mw-editsection-like plainlinks'
-- cfg['start-box-link-id']
-- The HTML "id" attribute for the links in the start box.
cfg['start-box-link-id'] = 'doc_editlinks'
----------------------------------------------------------------------------------------------------
-- {{fmbox}} template configuration
----------------------------------------------------------------------------------------------------
-- cfg['fmbox-id']
-- The id sent to the "id" parameter of the {{fmbox}} template.
cfg['fmbox-id'] = 'documentation-meta-data'
-- cfg['fmbox-style']
-- The value sent to the style parameter of {{fmbox}}.
cfg['fmbox-style'] = ''
-- cfg['fmbox-textstyle']
-- The value sent to the "textstyle parameter of {{fmbox}}.
cfg['fmbox-textstyle'] = 'font-size: small'
----------------------------------------------------------------------------------------------------
-- Tracking category configuration
----------------------------------------------------------------------------------------------------
-- cfg['display-strange-usage-category']
-- Set to true to enable output of cfg['strange-usage-category'] if the module is used on a /doc subpage
-- or a /testcases subpage. This should be a boolean value (either true or false).
cfg['display-strange-usage-category'] = true
-- cfg['strange-usage-category']
-- Category to output if cfg['display-strange-usage-category'] is set to true and the module is used on a
-- /doc subpage or a /testcases subpage.
cfg['strange-usage-category'] = 'Wikipedia pages with strange ((documentation)) usage'
--[[
----------------------------------------------------------------------------------------------------
-- End configuration
--
-- Don't edit anything below this line.
----------------------------------------------------------------------------------------------------
--]]
return cfg
c0991af7f04ef8f2b12d94f64d2e0ea5968d2413
Template:Efn
10
187
385
384
2024-08-04T12:22:09Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude><!--
****** 注意 *****
請勿添加任何中文的「註」或「注」功能,
否則會干擾後台對下面幾個保留字的操作,
所有中文功能已遷移至[[Template:noteTag]]。
--></noinclude><includeonly>{{#if:{{{name|}}}
|{{#tag:ref|{{{1|{{{reference|}}}}}}|name={{{name|}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group|}}}
| #default = lower-alpha
}}
}}
|{{#tag:ref|{{{1|{{{reference|}}}}}}|group={{#switch: {{{group|}}}
| upper-alpha
| upper-roman
| lower-alpha
| lower-greek
| lower-roman = {{{group|}}}
| #default = lower-alpha
}}
}}
}}</includeonly><noinclude>
{{documentation|Template:notelist/doc}}
</noinclude>
b05db3eed085ea7cf437f05625e1e71eedea9e85
Template:!!
10
188
387
386
2024-08-04T12:22:10Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
||<noinclude>{{Documentation}}</noinclude>
868ada04d0812624aa39b895a7fc297c0827d92d
Template:Documentation subpage
10
101
389
271
2024-08-04T12:22:10Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{Original-recipe|{{{Orig|}}}}}}
| <!--
-->{{Mbox<!--
-->| type = content<!--
-->| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
-->| text = <!--
---->此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。<!--
----><small><!--
------>此頁面可能不打算被直接閱讀。<!--
------><br><!--
------>使用[[Help:魔术字#变量|變量]]的-{zh-hans:链接;zh-hant:連結;}-可能看起來已損壞,事實上,這是有用途的連結,因此請勿將其替換為[[寫死]]的頁面名稱或URL。<!--
----></small><!--
-->}}<!--
-->{{#if:{{{inhib|{{{inhibit|x}}}}}}<!--
-->| <!--
-->| [[Category:模板說明文件|{{PAGENAME}}]]<!--
-->}}
| <!--
-->{{#switch:{{SUBPAGENAME}}<!--
-->| {{{override}}}| doc | Doc | documentation | Documentation | 文档 | 文件 = <!--
---->{{#ifeq:{{{doc-notice|show}}}<!--
---->| show<!--
---->| <!--
------>{{Mbox<!--
------>| type = notice<!--
------>| image = [[File:Edit-copy green.svg|40px|alt=|link=]]<!--
------>| text = <!--
-------->'''此頁面是[[{{NAMESPACE}}:{{{1|{{BASEPAGENAME}}}}}]]的[[那艺娜维基:模板文件頁模式|{{NSPN}}]]。'''<!--
--------><br><!--
--------><small>此頁面可能包含了模板的使用說明、[[那艺娜维基:頁面分類|分類]]和其他内容。</small><!--
------>}}<!--
---->}}<!--
---->{{DEFAULTSORT:{{PAGENAME}}}}<!--
---->{{#if:{{{inhibit|}}}<!--
---->| <!--
---->| [[Category:{{#switch:{{NAMESPACE}}|User=用户|Wikipedia=维基百科|Template=模板}}说明文件]]<!--
---->}}<!--
-->}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
a29fcace7b5ee767264d3f8874aa71d0eb6ec03d
Template:Tag
10
189
391
390
2024-08-04T12:22:11Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<code style="white-space:nowrap;">{{#switch:{{{2|pair}}}
|c|close = <!--nothing-->
|s|single
|o|open
|p|pair = <{{{1|tag}}}{{#if:{{{參數|{{{参数|{{{params|{{{attribs|{{{4|}}}}}}}}}}}}}}}| {{{參數|{{{参数|{{{params|{{{attribs|{{{4|}}}}}}}}}}}}}}}}}
}}{{#switch:{{{2|pair}}}
|c|close|关|關|右 = {{{內容|{{{内容|{{{文字|{{{content|{{{3|}}}}}}}}}}}}}}}
|s|single =  />
|o|open|开|開|左 = >{{{內容|{{{内容|{{{文字|{{{content|{{{3|}}}}}}}}}}}}}}}
|p|pair = >{{{內容|{{{内容|{{{文字|{{{content|{{{3|...}}}}}}}}}}}}}}}
}}{{#switch:{{{2|pair}}}
|s|single
|o|open|开|開|左 = <!--nothing-->
|c|close|关|關|右
|p|pair = </{{{1|tag}}}>
}}</code><noinclude>
{{documentation}}
</noinclude>
f159dd876de61be362b572be895a22804a8b1017
Template:TemplateData header
10
107
393
209
2024-08-04T12:22:11Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="templatedata-header">{{#if:{{{noheader|}}}| |以下是该模板的{{#if:{{{nolink|}}}|-{zh-cn:模板数据;zh-tw:模板資料}-|[[那艺娜维基:模板数据|-{zh-cn:模板数据;zh-tw:模板資料}-]]}},适用于[[那艺娜维基:可视化编辑器|-{zh-cn:可视化编辑器;zh-tw:視覺化編輯器;}-]]等工具。}}
'''{{{1|{{BASEPAGENAME}}}}}-{zh-cn:模板数据;zh-tw:模板資料}-'''
</div><includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox||
[[Category:模板数据文档]]
}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
d02fc282d251516ba7c50d0ba1fbca94c816036d
Module:Protection banner/config
828
111
395
275
2024-08-04T12:22:12Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module provides configuration data for [[Module:Protection banner]].
return {
--------------------------------------------------------------------------------
--
-- BANNER DATA
--
--------------------------------------------------------------------------------
--[[
-- Banner data consists of six fields:
-- * text - the main protection text that appears at the top of protection
-- banners.
-- * explanation - the text that appears below the main protection text, used
-- to explain the details of the protection.
-- * tooltip - the tooltip text you see when you move the mouse over a small
-- padlock icon.
-- * link - the page that the small padlock icon links to.
-- * alt - the alt text for the small padlock icon. This is also used as tooltip
-- text for the large protection banners.
-- * image - the padlock image used in both protection banners and small padlock
-- icons.
--
-- The module checks in three separate tables to find a value for each field.
-- First it checks the banners table, which has values specific to the reason
-- for the page being protected. Then the module checks the defaultBanners
-- table, which has values specific to each protection level. Finally, the
-- module checks the masterBanner table, which holds data for protection
-- templates to use if no data has been found in the previous two tables.
--
-- The values in the banner data can take parameters. These are specified
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name
-- enclosed in curly braces).
--
-- Available parameters:
--
-- ${CURRENTVERSION} - a link to the page history or the move log, with the
-- display message "current-version-edit-display" or
-- "current-version-move-display".
--
-- ${EDITREQUEST} - a link to create an edit request for the current page.
--
-- ${EXPIRY} - the protection expiry date in the format DD Month YYYY. If
-- protection is indefinite or is not set, this is the blank string.
--
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. "Please discuss any changes
-- on the talk page; you may submit a request to ask an administrator to make
-- an edit if it is minor or supported by consensus."
--
-- ${IMAGELINK} - a link to set the image to, depending on the protection
-- action and protection level.
--
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry
-- is set. E.g. "Editing of this page by new or unregistered users is currently
-- disabled until dd Month YYYY."
--
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation
-- so that it can be used in run-on sentences.
--
-- ${PAGETYPE} - the type of the page, e.g. "article" or "template".
-- Defined in the cfg.pagetypes table.
--
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.
-- "Editing of this page by new or unregistered users is currently disabled"
--
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the
-- template.
--
-- ${PROTECTIONLEVEL} - the protection level, e.g. "fully protected" or
-- "semi-protected".
--
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,
-- depending on the protection action.
--
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links
-- straight to that talk page section.
--
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to
-- create a blurb like "This template is semi-protected", or "This article is
-- move-protected until DD Month YYYY".
--
-- ${VANDAL} - links for the specified username (or the root page name)
-- using Module:Vandal-m.
--
-- Functions
--
-- For advanced users, it is possible to use Lua functions instead of strings
-- in the banner config tables. Using functions gives flexibility that is not
-- possible just by using parameters. Functions take two arguments, the
-- protection object and the template arguments, and they must output a string.
--
-- For example:
--
-- text = function (protectionObj, args)
-- if protectionObj.level == 'autoconfirmed' then
-- return 'foo'
-- else
-- return 'bar'
-- end
-- end
--
-- Some protection object properties and methods that may be useful:
-- protectionObj.action - the protection action
-- protectionObj.level - the protection level
-- protectionObj.reason - the protection reason
-- protectionObj.expiry - the expiry. Nil if unset, the string "indef" if set
-- to indefinite, and the protection time in unix time if temporary.
-- protectionObj.protectionDate - the protection date in unix time, or nil if
-- unspecified.
-- protectionObj.bannerConfig - the banner config found by the module. Beware
-- of editing the config field used by the function, as it could create an
-- infinite loop.
-- protectionObj:isProtected - returns a boolean showing whether the page is
-- protected.
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is
-- temporary.
-- protectionObj:isIncorrect - returns a boolean showing whether the protection
-- template is incorrect.
--]]
-- The master banner data, used if no values have been found in banners or
-- defaultBanners.
masterBanner = {
text = '${INTROBLURB}',
explanation = '${EXPLANATIONBLURB}',
tooltip = '${TOOLTIPBLURB}',
link = '${IMAGELINK}',
alt = '页面被${PROTECTIONLEVEL}'
},
-- The default banner data. This holds banner data for different protection
-- levels.
-- *required* - this table needs edit, move, autoreview and upload subtables.
defaultBanners = {
edit = {},
move = {},
autoreview = {
autoconfirmed = {
alt = 'Page protected with pending changes level 1',
tooltip = 'All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users',
image = 'Padlock-silver-light.svg'
},
default = {
alt = 'Page protected with pending changes level 2',
tooltip = 'All edits by users who are not reviewers or administrators are'
.. ' subject to review prior to becoming visible to unregistered users',
image = 'Padlock-orange.svg'
}
},
upload = {}
},
-- The banner data. This holds banner data for different protection reasons.
-- In fact, the reasons specified in this table control which reasons are
-- valid inputs to the first positional parameter.
--
-- There is also a non-standard "description" field that can be used for items
-- in this table. This is a description of the protection reason for use in the
-- module documentation.
--
-- *required* - this table needs edit, move, autoreview and upload subtables.
banners = {
edit = {
blp = {
description = '为了遵守'
.. ' [[那艺娜维基:生者傳記'
.. '|生者傳記]]方针而保护的页面',
text = '${INTROFRAGMENT}以遵守'
.. ' [[那艺娜维基:生者傳記'
.. "|维基百科"
.. '生者傳記]]方针。',
tooltip = '${TOOLTIPFRAGMENT}以遵守'
.. '生者傳記方针',
},
dmca = {
description = '因[[數字千年版權法]]移除通知而'
.. '被维基媒体基金会保护的页面',
explanation = function (protectionObj, args)
local ret = '为回应数字'
.. ' 千年版权法案(DMCA)下,文中部分内容'
.. ' 权利人发来的通知,维基媒体基金会已根据'
.. ' 适用法律采取行动,删除并限制了相关'
.. ' 内容。'
if args.notice then
ret = ret .. '可以在此查看删除请求副本:'
.. args.notice .. '。'
end
ret = ret .. '有关更多信息,包括讨论'
.. '如何提交反通知的网站,请参阅'
.. '[[那艺娜维基:基金會行動]]及条目的${TALKPAGE}。'
.. "'''在限制撤销之前,"
.. "请勿移除此模板'''。"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
dispute = {
description = '由于编辑争议而被保护的页面',
text = function (protectionObj, args)
-- Find the value of "disputes".
local display = '争议'
local disputes
if args.section then
disputes = string.format(
'[[%s:%s#%s|%s]]',
mw.site.namespaces[protectionObj.title.namespace].talk.name,
protectionObj.title.text,
args.section,
display
)
else
disputes = display
end
-- Make the blurb, depending on the expiry.
local msg
if type(protectionObj.expiry) == 'number' then
msg = '${INTROFRAGMENT},或直到编辑%s被解决。'
else
msg = '${INTROFRAGMENT},直到编辑%s被解决。'
end
return string.format(msg, disputes)
end,
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
tooltip = '由于编辑争议,${TOOLTIPFRAGMENT}',
},
mainpage = {
description = '由于在[[那艺娜维基:首页]]展示而被保护的页面',
text = '此文件目前已'
.. '获[[那艺娜维基:獲保護頁面|保护]]而'
.. '无法编辑,因为它当前或即将'
.. '在[[那艺娜维基:首页]]上展示。',
explanation = '首页上的图像由于其高可见性而被'
.. '保护。任何必要的更改请在${TALKPAGE}上讨论。'
.. '<br /><span style="font-size:90%;">'
.. "'''致管理员:'''一旦此图像从首页撤下,"
.. '请取消保护此文件,或酌情减少到'
.. '半保护。</span>',
},
office = {
description = '被维基媒体基金会保护的页面',
text = function (protectionObj, args)
local ret = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。'
if protectionObj.protectionDate then
ret = ret .. '此页面自${PROTECTIONDATE}起被保护。'
end
return ret
end,
explanation = "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿解除此页面的保护"
.. "状态,除非您得到维基媒体基金会"
.. "的授权。'''",
image = 'Office-protection-shackle-WMFlogo.svg',
},
reset = {
description = '被维基媒体基金会保护,并将其'
.. '“重置”为纯粹版本的页面',
text = '此${PAGETYPE}目前正在接受'
.. '[[那艺娜维基:基金會行動|維基媒體基金會辦公室]]'
.. '的审查,'
.. '并获保护。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.protectionDate then
ret = ret .. '在${PROTECTIONDATE},此${PAGETYPE}'
else
ret = ret .. '此${PAGETYPE}已'
end
ret = ret .. '被简化为'
.. '“纯粹”的版本,以便可以完全'
.. '重写,确保其符合'
.. '[[WP:NPOV|中立的观点]]和[[WP:V|可供查证]]方针。'
.. '重写版本最终将会向所有编者开放,'
.. '通常的维基百科方针都将适用于此页面,并将严格'
.. '执行。此${PAGETYPE}在重建时已被'
.. '${PROTECTIONLEVEL}。\n\n'
.. '直接添加任何从此${PAGETYPE}'
.. '保护前版本中得到的资料,或'
.. '任何添加至此${PAGETYPE}中的'
.. '无来源资料,都将被删除。相关讨论页也于'
.. '同一天清空。\n\n'
.. "如果您可以编辑此页面,请首先在"
.. "${TALKPAGE}上讨论任何修改或添加动作。'''请勿覆盖"
.. "此操作,且不要解除此页面的保护状态,"
.. "除非您已获得维基媒体基金会的"
.. "授权。任何编者均不可移除此通知。'''"
return ret
end,
image = 'Office-protection-shackle-WMFlogo.svg',
},
sock = {
description = '由于滥用'
.. '[[那艺娜维基:傀儡|傀儡]]而被保护的页面。',
text = '${INTROFRAGMENT},以防止被'
.. '[[那艺娜维基:封禁方针|封禁]]或被'
.. '[[那艺娜维基:編輯禁制方針|編輯禁制]]用户的[[那艺娜维基:傀儡|傀儡]]'
.. '编辑。',
tooltip = '为防止被封禁或被編輯禁制用户的傀儡编辑,'
.. '${TOOLTIPFRAGMENT}',
},
template = {
description = '[[那艺娜维基:高風險模板|高風險模板]]'
.. '和Lua模块',
text = '此${PAGETYPE}为[[那艺娜维基:高風險模板|高風險模板]],'
.. '已被永久[[那艺娜维基:獲保護頁面|保護]]。',
explanation = '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]或'
.. '[[那艺娜维基:模板编辑员|模板编辑员]]'
.. '${EDITREQUEST}。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
tooltip = '此高风险${PAGETYPE}已被永久${PROTECTIONLEVEL}'
.. ',以避免破坏',
alt = '被永久保护的${PAGETYPE}',
},
usertalk = {
description = '由于特定用户破坏而'
.. '被保护的页面',
text = '${INTROFRAGMENT},以防止${VANDAL}使用其进行破坏性编辑,'
.. '如滥用'
.. '{{[[Template:unblock|unblock]]}}模板。',
explanation = '如果您不能编辑此用户讨论页,且需要'
.. '修改或留言,您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求编辑'
.. '|请求编辑]],'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],'
.. '[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏|破坏]]而被保护的页面',
text = '由于[[那艺娜维基:破坏|破坏]],${INTROFRAGMENT}。',
explanation = function (protectionObj, args)
local ret = ''
if protectionObj.level == 'sysop' then
ret = ret .. "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。'
end
return ret .. '${EXPLANATIONBLURB}'
end,
tooltip = '由于破坏,${TOOLTIPFRAGMENT}',
}
},
move = {
dispute = {
description = '由于标题争议而'
.. '被移动保护的页面',
explanation = "此保护'''不是'''对"
.. '${CURRENTVERSION}的认可。${EXPLANATIONBLURB}',
image = 'Move-protection-shackle.svg'
},
vandalism = {
description = '由于'
.. '[[那艺娜维基:破坏#移动破坏'
.. '|移动破坏]]而被保护的页面'
}
},
autoreview = {},
upload = {}
},
--------------------------------------------------------------------------------
--
-- GENERAL DATA TABLES
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Protection blurbs
--------------------------------------------------------------------------------
-- This table produces the protection blurbs available with the
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and
-- protection level, and is checked by the module in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionBlurbs = {
edit = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|'
.. '保護]],无法编辑',
autoconfirmed = '[[那艺娜维基:用户权限'
.. '级别#新用户|新用户]]或[[那艺娜维基:用户权限级别#匿名'
.. '用户|匿名用户]]用户编辑此${PAGETYPE}目前[[那艺娜维基:獲保護頁面|已禁用]]',
},
move = {
default = '此${PAGETYPE}当前已被[[那艺娜维基:獲保護頁面|保護]],'
.. '无法[[Help:页面重命名|移动]]'
},
autoreview = {
autoconfirmed = 'All edits made to this ${PAGETYPE} by'
.. ' [[那艺娜维基:用户权限级别#新用户|新用户]] or'
.. ' [[那艺娜维基:用户权限级别#匿名用户|匿名用户]]'
.. ' users are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]',
default = 'All edits made to this ${PAGETYPE} by users who are not'
.. ' [[那艺娜维基:Reviewing|reviewers]] or'
.. ' [[那艺娜维基:管理员|管理员]] are currently'
.. ' [[那艺娜维基:Pending changes|subject to review]]'
},
upload = {
default = '上传此${PAGETYPE}的新版本目前已禁用'
}
},
--------------------------------------------------------------------------------
-- Explanation blurbs
--------------------------------------------------------------------------------
-- This table produces the explanation blurbs available with the
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,
-- protection level, and whether the page is a talk page or not. If the page is
-- a talk page it will have a talk key of "talk"; otherwise it will have a talk
-- key of "subject". The table is checked in the following order:
-- 1. page's protection action, page's protection level, page's talk key
-- 2. page's protection action, page's protection level, default talk key
-- 3. page's protection action, default protection level, page's talk key
-- 4. page's protection action, default protection level, default talk key
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
explanationBlurbs = {
edit = {
autoconfirmed = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '${EDITREQUEST},在${TALKPAGE}上讨论更改,'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。如果您'
.. '不能编辑,且希望修改此${PAGETYPE},您可以'
.. '[[那艺娜维基:请求保护页面'
.. '#请求解除保护'
.. '|请求解除保护]],[[Special:用户登录|登录]],'
.. '或[[Special:创建账户|创建帐户]]。',
},
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有[[那艺娜维基:共识'
.. '|共识]]基础,您可以向'
.. '[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。您也可以[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '您可以[[那艺娜维基:请求'
.. '保护页面#请求编辑|请求'
.. '编辑]]此页面,或[[那艺娜维基:请求'
.. '保护页面#请求解除保护'
.. '|请求]]解除页面保护。',
}
},
move = {
default = {
subject = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在${TALKPAGE}或[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '该页面仍可编辑,但在解除保护后'
.. '才能移动。请在[[那艺娜维基:移動請求]]'
.. '上讨论任何移动建议。您也可以'
.. '[[那艺娜维基:请求保护页面|请求]]解除'
.. '页面保护。',
}
},
autoreview = {
default = {
reviewer = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} will not be visible to readers'
.. ' until they are accepted by a reviewer or an administrator.'
.. ' To avoid the need for your edits to be reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]]. Experienced editors may also'
.. ' request the [[那艺娜维基:Reviewing|reviewer user right]].',
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. ' Edits to this ${PAGETYPE} by new and unregistered users'
.. ' will not be visible to readers until they are accepted by'
.. ' a reviewer. To avoid the need for your edits to be'
.. ' reviewed, you may'
.. ' [[那艺娜维基:Requests for page protection'
.. '#Current requests for reduction in protection level'
.. '|request unprotection]], [[Special:Userlogin|log in]], or'
.. ' [[Special:UserLogin/signup|create an account]].'
},
},
upload = {
default = {
default = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '页面可能仍可以编辑,但在解除保护后'
.. '才能上传文件的新版本。您可以使用'
.. '[[那艺娜维基:编辑请求|受保护页面编辑请求]]'
.. '来请求上传新版本,或者您'
.. '可以[[那艺娜维基:请求保护页面|请求]]'
.. '解除文件保护。'
}
}
},
--------------------------------------------------------------------------------
-- Protection levels
--------------------------------------------------------------------------------
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which
-- produces a short label for different protection levels. It is sorted by
-- protection action and protection level, and is checked in the following
-- order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
protectionLevels = {
edit = {
default = '全保护',
templateeditor = '模板保护',
extendedconfirmed = '延伸確認保護',
autoconfirmed = '半保护',
},
move = {
default = '移动保护'
},
autoreview = {
},
upload = {
default = '文件保护'
}
},
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- This table lists different padlock images for each protection action and
-- protection level. It is used if an image is not specified in any of the
-- banner data tables, and if the page does not satisfy the conditions for using
-- the ['image-filename-indef'] image. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
images = {
edit = {
default = 'Full-protection-shackle-block.svg',
templateeditor = 'Template-protection-shackle-picture-1.svg',
extendedconfirmed = 'Extended-protection-shackle-account-pro-plus.svg',
autoconfirmed = 'Semi-protection-shackle.svg'
},
move = {
default = 'Move-protection-shackle.svg',
},
autoreview = {
autoconfirmed = 'Padlock-silver-light.svg',
default = 'Padlock-orange.svg'
},
upload = {
default = 'Upload-protection-shackle.svg'
}
},
-- Pages with a reason specified in this table will show the special "indef"
-- padlock, defined in the 'image-filename-indef' message, if no expiry is set.
indefImageReasons = {
template = true
},
--------------------------------------------------------------------------------
-- Image links
--------------------------------------------------------------------------------
-- This table provides the data for the ${IMAGELINK} parameter, which gets
-- the image link for small padlock icons based on the page's protection action
-- and protection level. It is checked in the following order:
-- 1. page's protection action, page's protection level
-- 2. page's protection action, default protection level
-- 3. "edit" protection action, default protection level
--
-- It is possible to use banner parameters inside this table.
-- *required* - this table needs edit, move, autoreview and upload subtables.
imageLinks = {
edit = {
default = '那艺娜维基:保護方針#全保护',
templateeditor = '那艺娜维基:保護方針#模板保护',
extendedconfirmed = '那艺娜维基:保護方針#延伸確認保護',
autoconfirmed = '那艺娜维基:保護方針#半保护'
},
move = {
default = '那艺娜维基:保護方針#移动保护'
},
autoreview = {
autoconfirmed = '那艺娜维基:保護方針#pc1',
reviewer = '那艺娜维基:保護方針#pc2'
},
upload = {
default = '那艺娜维基:保護方針#文件保护'
}
},
--------------------------------------------------------------------------------
-- Padlock indicator names
--------------------------------------------------------------------------------
-- This table provides the "name" attribute for the <indicator> extension tag
-- with which small padlock icons are generated. All indicator tags on a page
-- are displayed in alphabetical order based on this attribute, and with
-- indicator tags with duplicate names, the last tag on the page wins.
-- The attribute is chosen based on the protection action; table keys must be a
-- protection action name or the string "default".
padlockIndicatorNames = {
autoreview = 'pp-autoreview',
default = 'pp-default'
},
--------------------------------------------------------------------------------
-- Protection categories
--------------------------------------------------------------------------------
--[[
-- The protection categories are stored in the protectionCategories table.
-- Keys to this table are made up of the following strings:
--
-- 1. the expiry date
-- 2. the namespace
-- 3. the protection reason (e.g. "dispute" or "vandalism")
-- 4. the protection level (e.g. "sysop" or "autoconfirmed")
-- 5. the action (e.g. "edit" or "move")
--
-- When the module looks up a category in the table, first it will will check to
-- see a key exists that corresponds to all five parameters. For example, a
-- user page semi-protected from vandalism for two weeks would have the key
-- "temp-user-vandalism-autoconfirmed-edit". If no match is found, the module
-- changes the first part of the key to "all" and checks the table again. It
-- keeps checking increasingly generic key combinations until it finds the
-- field, or until it reaches the key "all-all-all-all-all".
--
-- The module uses a binary matrix to determine the order in which to search.
-- This is best demonstrated by a table. In this table, the "0" values
-- represent "all", and the "1" values represent the original data (e.g.
-- "indef" or "file" or "vandalism").
--
-- expiry namespace reason level action
-- order
-- 1 1 1 1 1 1
-- 2 0 1 1 1 1
-- 3 1 0 1 1 1
-- 4 0 0 1 1 1
-- 5 1 1 0 1 1
-- 6 0 1 0 1 1
-- 7 1 0 0 1 1
-- 8 0 0 0 1 1
-- 9 1 1 1 0 1
-- 10 0 1 1 0 1
-- 11 1 0 1 0 1
-- 12 0 0 1 0 1
-- 13 1 1 0 0 1
-- 14 0 1 0 0 1
-- 15 1 0 0 0 1
-- 16 0 0 0 0 1
-- 17 1 1 1 1 0
-- 18 0 1 1 1 0
-- 19 1 0 1 1 0
-- 20 0 0 1 1 0
-- 21 1 1 0 1 0
-- 22 0 1 0 1 0
-- 23 1 0 0 1 0
-- 24 0 0 0 1 0
-- 25 1 1 1 0 0
-- 26 0 1 1 0 0
-- 27 1 0 1 0 0
-- 28 0 0 1 0 0
-- 29 1 1 0 0 0
-- 30 0 1 0 0 0
-- 31 1 0 0 0 0
-- 32 0 0 0 0 0
--
-- In this scheme the action has the highest priority, as it is the last
-- to change, and the expiry has the least priority, as it changes the most.
-- The priorities of the expiry, the protection level and the action are
-- fixed, but the priorities of the reason and the namespace can be swapped
-- through the use of the cfg.bannerDataNamespaceHasPriority table.
--]]
-- If the reason specified to the template is listed in this table,
-- namespace data will take priority over reason data in the protectionCategories
-- table.
reasonsWithNamespacePriority = {
vandalism = true,
},
-- The string to use as a namespace key for the protectionCategories table for each
-- namespace number.
categoryNamespaceKeys = {
[ 2] = 'user',
[ 3] = 'user',
[ 4] = 'project',
[ 6] = 'file',
[ 8] = 'mediawiki',
[ 10] = 'template',
[ 12] = 'project',
[ 14] = 'category',
[100] = 'portal',
[828] = 'module',
},
protectionCategories = {
['all|all|all|all|all'] = '被保护的页面',
['all|all|office|all|all'] = '被基金会保护的页面',
['all|all|reset|all|all'] = '被基金会保护的页面',
['all|all|dmca|all|all'] = '被基金会保护的页面',
['all|all|mainpage|all|all'] = '被保护的首页文件',
['all|template|all|all|edit'] = '被保護的模板',
['all|all|all|autoconfirmed|edit'] = '被半保护的页面',
['indef|all|all|autoconfirmed|edit'] = '被永久半保护的页面',
['all|all|blp|autoconfirmed|edit'] = '被永久半保护的生者传记',
['temp|all|blp|autoconfirmed|edit'] = '被暂时半保护的生者传记',
['all|all|dispute|autoconfirmed|edit'] = '由于争议而被半保护的页面',
['all|all|sock|autoconfirmed|edit'] = '由于滥用傀儡而被半保护的页面',
['all|all|vandalism|autoconfirmed|edit'] = '避免破坏而被半保护的页面',
['all|category|all|autoconfirmed|edit'] = '被半保護的分類',
['all|file|all|autoconfirmed|edit'] = '被半保護的圖像',
['all|portal|all|autoconfirmed|edit'] = '被半保護的主題',
['all|project|all|autoconfirmed|edit'] = '被半保護的專題',
['all|talk|all|autoconfirmed|edit'] = '被半保護的討論頁',
['all|template|all|autoconfirmed|edit'] = '被半保護的模板',
['all|user|all|autoconfirmed|edit'] = '被半保護的用戶頁',
['all|template|all|templateeditor|edit'] = '被模板保護的模板',
['all|all|blp|sysop|edit'] = '被永久保护的生者传记',
['temp|all|blp|sysop|edit'] = '被暂时保护的生者传记',
['all|all|dispute|sysop|edit'] = '由于争议而被保护的页面',
['all|all|sock|sysop|edit'] = '由于滥用傀儡而被保护的页面',
['all|all|vandalism|sysop|edit'] = '避免破坏而被保护的页面',
['all|category|all|sysop|edit'] = '被保護的分類',
['all|file|all|sysop|edit'] = '被保護的圖像',
['all|project|all|sysop|edit'] = '被保護的專題',
['all|talk|all|sysop|edit'] = '被保護的討論頁',
['all|template|all|sysop|edit'] = '被保護的模板',
['all|user|all|sysop|edit'] = '被保護的用戶頁',
['all|module|all|all|edit'] = '被保护的模块',
['all|module|all|templateeditor|edit'] = '被模板保护的模块',
['all|module|all|autoconfirmed|edit'] = '被半保护的模块',
['all|all|all|sysop|move'] = '被移動保護的頁面',
['indef|all|all|sysop|move'] = '被永久移動保護的頁面',
['all|all|dispute|sysop|move'] = '由于争议而被移动保护的页面',
['all|all|vandalism|sysop|move'] = '避免破坏而被移动保护的页面',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|portal|all|sysop|move'] = '被移動保護的主題',
['all|project|all|sysop|move'] = '被移動保護的專題',
['all|talk|all|sysop|move'] = '被移動保護的討論頁',
['all|template|all|sysop|move'] = '被移動保護的模板',
['all|user|all|sysop|move'] = '被移動保護的用戶頁',
['all|all|all|autoconfirmed|autoreview'] = 'Wikipedia pending changes protected pages',
['all|all|all|reviewer|autoreview'] = 'Wikipedia pending changes protected pages (level 2)',
['all|file|all|all|upload'] = '被文件保护的文件',
},
--------------------------------------------------------------------------------
-- Expiry category config
--------------------------------------------------------------------------------
-- This table configures the expiry category behaviour for each protection
-- action.
-- * If set to true, setting that action will always categorise the page if
-- an expiry parameter is not set.
-- * If set to false, setting that action will never categorise the page.
-- * If set to nil, the module will categorise the page if:
-- 1) an expiry parameter is not set, and
-- 2) a reason is provided, and
-- 3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck
-- table.
expiryCheckActions = {
edit = nil,
move = false,
autoreview = true,
upload = false
},
reasonsWithoutExpiryCheck = {
blp = true,
template = true,
},
--------------------------------------------------------------------------------
-- Pagetypes
--------------------------------------------------------------------------------
-- This table produces the page types available with the ${PAGETYPE} parameter.
-- Keys are namespace numbers, or the string "default" for the default value.
pagetypes = {
[0] = '条目',
[6] = '文件',
[10] = '模板',
[14] = '分类',
[828] = '模块',
default = '页面'
},
--------------------------------------------------------------------------------
-- Strings marking indefinite protection
--------------------------------------------------------------------------------
-- This table contains values passed to the expiry parameter that mean the page
-- is protected indefinitely.
indefStrings = {
['indef'] = true,
['indefinite'] = true,
['indefinitely'] = true,
['infinite'] = true,
},
--------------------------------------------------------------------------------
-- Group hierarchy
--------------------------------------------------------------------------------
-- This table maps each group to all groups that have a superset of the original
-- group's page editing permissions.
hierarchy = {
sysop = {},
reviewer = {'sysop'},
filemover = {'sysop'},
templateeditor = {'sysop'},
extendedconfirmed = {'sysop'},
autoconfirmed = {'reviewer', 'filemover', 'templateeditor', 'extendedconfirmed'},
user = {'autoconfirmed'},
['*'] = {'user'}
},
--------------------------------------------------------------------------------
-- Wrapper templates and their default arguments
--------------------------------------------------------------------------------
-- This table contains wrapper templates used with the module, and their
-- default arguments. Templates specified in this table should contain the
-- following invocation, and no other template content:
--
-- {{#invoke:Protection banner|main}}
--
-- If other content is desired, it can be added between
-- <noinclude>...</noinclude> tags.
--
-- When a user calls one of these wrapper templates, they will use the
-- default arguments automatically. However, users can override any of the
-- arguments.
--
-- [[那艺娜维基:模板消息/保護模板]]
wrappers = {
['Template:Pp-protected'] = {},
['Template:Pp-semi-blp'] = {'blp'},
-- we don't need Template:Pp-create
['Template:Pp-dispute'] = {'dispute'},
-- ['Template:Pp-main-page'] = {'mainpage'},
['Template:Pp-move'] = {action = 'move'},
['Template:Pp-move-dispute'] = {'dispute', action = 'move'},
-- we don't need Template:Pp-move-indef
['Template:Pp-move-vandalism'] = {'vandalism', action = 'move'},
['Template:Pp-office'] = {'office'},
['Template:Pp-office-dmca'] = {'dmca'},
['Template:Pp-pc1'] = {action = 'autoreview', small = true},
['Template:Pp-pc2'] = {action = 'autoreview', small = true},
['Template:Pp-reset'] = {'reset'},
['Template:Pp-semi-indef'] = {small = true},
['Template:Pp-semi-sock'] = {'sock'},
['Template:Pp-template'] = {'template', small = true},
['Template:Pp-upload'] = {action = 'upload'},
['Template:Pp-usertalk'] = {'usertalk'},
['Template:Pp-vandalism'] = {'vandalism'},
},
--------------------------------------------------------------------------------
--
-- MESSAGES
--
--------------------------------------------------------------------------------
msg = {
--------------------------------------------------------------------------------
-- Intro blurb and intro fragment
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${INTROBLURB} and
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use
-- intro-blurb-noexpiry or intro-fragment-noexpiry.
-- It is possible to use banner parameters in these messages.
['intro-blurb-expiry'] = '${PROTECTIONBLURB}至${EXPIRY}。',
['intro-blurb-noexpiry'] = '${PROTECTIONBLURB}。',
['intro-fragment-expiry'] = '${PROTECTIONBLURB}至${EXPIRY},',
['intro-fragment-noexpiry'] = '${PROTECTIONBLURB}',
--------------------------------------------------------------------------------
-- Tooltip blurb
--------------------------------------------------------------------------------
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.
-- If the protection is temporary the tooltip-blurb-expiry message is used, and
-- if not the tooltip-blurb-noexpiry message is used.
-- It is possible to use banner parameters in these messages.
['tooltip-blurb-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY}。',
['tooltip-blurb-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}。',
['tooltip-fragment-expiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}至${EXPIRY},',
['tooltip-fragment-noexpiry'] = '此${PAGETYPE}已被${PROTECTIONLEVEL}',
--------------------------------------------------------------------------------
-- Special explanation blurb
--------------------------------------------------------------------------------
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages
-- in the MediaWiki namespace.
-- It is possible to use banner parameters in this message.
['explanation-blurb-nounprotect'] = '更多信息,请参见[[那艺娜维基:保護方針|'
.. '保護方針]]及${PROTECTIONLOG}。'
.. '请在${TALKPAGE}上讨论任何修改或添加动作。如果'
.. '编辑[[Help:小修改#何时标明编辑为小修改'
.. '|无争议]]或有'
.. '[[那艺娜维基:共识|共识]]基础,您可以'
.. '向[[那艺娜维基:管理员|管理员]]'
.. '${EDITREQUEST}。',
--------------------------------------------------------------------------------
-- Protection log display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the protection log link
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.
-- It is possible to use banner parameters in these messages.
['protection-log-display'] = '保护日志',
['pc-log-display'] = '待更改日志',
--------------------------------------------------------------------------------
-- Current version display values
--------------------------------------------------------------------------------
-- These messages determine the display values for the page history link
-- or the move log link produced by the ${CURRENTVERSION} parameter.
-- It is possible to use banner parameters in these messages.
['current-version-move-display'] = '当前标题',
['current-version-edit-display'] = '当前版本',
--------------------------------------------------------------------------------
-- Talk page
--------------------------------------------------------------------------------
-- This message determines the display value of the talk page link produced
-- with the ${TALKPAGE} parameter.
-- It is possible to use banner parameters in this message.
['talk-page-link-display'] = '讨论页',
--------------------------------------------------------------------------------
-- Edit requests
--------------------------------------------------------------------------------
-- This message determines the display value of the edit request link produced
-- with the ${EDITREQUEST} parameter.
-- It is possible to use banner parameters in this message.
['edit-request-display'] = '提出编辑请求',
--------------------------------------------------------------------------------
-- Expiry date format
--------------------------------------------------------------------------------
-- This is the format for the blurb expiry date. It should be valid input for
-- the first parameter of the #time parser function.
['expiry-date-format'] = 'Y F j',
--------------------------------------------------------------------------------
-- Tracking categories
--------------------------------------------------------------------------------
-- These messages determine which tracking categories the module outputs.
['tracking-category-incorrect'] = '保護狀態與保護標誌不符的頁面',
['tracking-category-template'] = '非模板和模块的模板保护页面',
--------------------------------------------------------------------------------
-- Images
--------------------------------------------------------------------------------
-- These are images that are not defined by their protection action and protection level.
['image-filename-indef'] = 'Full-protection-shackle-block.svg',
['image-filename-default'] = 'Transparent.gif',
--------------------------------------------------------------------------------
-- End messages
--------------------------------------------------------------------------------
}
--------------------------------------------------------------------------------
-- End configuration
--------------------------------------------------------------------------------
}
7094c99bbb3daa4ca9c6e7979c5de465b77c2398
Template:Rellink
10
190
397
396
2024-08-04T12:22:13Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Hatnote]]
cdce4d78e74458e05e7054ffb0c0faa2d571b546
Module:Transclusion count
828
115
399
277
2024-08-04T12:22:14Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.fetch(frame)
local template = nil
local return_value = nil
-- Use demo parameter if it exists, otherswise use current template name
local namespace = mw.title.getCurrentTitle().namespace
if frame.args["demo"] and frame.args["demo"] ~= "" then
template = frame.args["demo"]
elseif namespace == 10 then -- Template namespace
template = mw.title.getCurrentTitle().text
elseif namespace == 828 then -- Module namespace
template = (mw.site.namespaces[828].name .. ":" .. mw.title.getCurrentTitle().text)
end
-- If in template or module namespace, look up count in /data
if template ~= nil then
namespace = mw.title.new(template, "Template").namespace
if namespace == 10 or namespace == 828 then
template = mw.ustring.gsub(template, "/doc$", "") -- strip /doc from end
local index = mw.ustring.sub(mw.title.new(template).text,1,1)
local status, data = pcall(function ()
return(mw.loadData('Module:Transclusion_count/data/' .. (mw.ustring.find(index, "%a") and index or "other")))
end)
if status then
return_value = tonumber(data[mw.ustring.gsub(template, " ", "_")])
end
end
end
-- If database value doesn't exist, use value passed to template
if return_value == nil and frame.args[1] ~= nil then
local arg1=mw.ustring.match(frame.args[1], '[%d,]+')
if arg1 and arg1 ~= '' then
return_value = tonumber(frame:callParserFunction('formatnum', arg1, 'R'))
end
end
return return_value
end
-- Tabulate this data for [[那艺娜维基:Database reports/Templates transcluded on the most pages]]
function p.tabulate(frame)
local list = {}
for i = 65, 91 do
local data = mw.loadData('Module:Transclusion count/data/' .. ((i == 91) and 'other' or string.char(i)))
for name, count in pairs(data) do
table.insert(list, {mw.title.new(name, "Template").fullText, count})
end
end
table.sort(list, function(a, b)
return (a[2] == b[2]) and (a[1] < b[1]) or (a[2] > b[2])
end)
local lang = mw.getContentLanguage();
for i = 1, #list do
list[i] = ('|-\n| %d || [[%s]] || %s\n'):format(i, list[i][1]:gsub('_', ' '), lang:formatNum(list[i][2]))
end
return table.concat(list)
end
return p
c08ee42f72543653cc35e9f1ae778d67e049f7b4
Template:Efn-ur
10
191
401
400
2024-08-04T12:22:15Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{efn|name={{{name|}}}|group=upper-roman|1={{{1|}}}}}</includeonly><noinclude>
{{documentation|Template:notelist/doc}}
</noinclude>
73c8ddd55bffed98bf9b211a8a0cdbba28a1040a
Template:Notelist-ur
10
192
403
402
2024-08-04T12:22:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{notelist|1={{{1|{{{refs|{{{notes|}}}}}}}}}|group=upper-roman}}</includeonly><noinclude>
{{documentation|Template:Notelist/doc}}
</noinclude>
64ef89ca9259c7c15888a74981a6882f7839ebca
Template:Fake heading
10
193
405
404
2024-08-04T12:22:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<templatestyles src="Fake heading/styles.css"/><div class="fakeHeading {{#switch: {{{level|{{{sub|}}}}}}
| 1 = h1
| 2 | #default = h2
| 3 = h3
| 4 = h4
| 5 = h5
| 6 = h6
}}">{{{1|分段}}}</div><noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage and interwikis go on Wikidata. -->
</noinclude>
57b618039321d9c272af2f821696f88e30de9ae7
Template:Fake heading/styles.css
10
194
407
406
2024-08-04T12:22:17Z
黑茶
2
导入1个版本
sanitized-css
text/css
.fakeHeading {
overflow: hidden;
page-break-after: avoid;
}
.h1,.h2 {
border-bottom: 1px solid #aaa;
font-family: 'Linux Libertine','Georgia','Times',serif;
font-weight: normal;
line-height: 1.3;
margin-top: 1em;
margin-bottom: 0.25em;
padding: 0;
}
.h1 {
font-size: 1.8em;
}
.h2 {
font-size: 1.5em;
}
.h3,.h4,.h5,.h6 {
font-family: sans-serif;
font-weight: bold;
line-height: 1.6;
margin-top: 0.3em;
margin-bottom: 0;
padding-top: 0.5em;
padding-bottom: 0;
}
.h3 {
font-size: 1.2em;
}
.h4,.h5,.h6 {
font-size: 100%;
}
1171ae88a7b7b14b24abcc01a3fb695d753fafcc
Template:Markup
10
195
409
408
2024-08-04T12:22:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{| style="{{#if:{{{width|}}}|width:{{{width}}};}} margin-top:0;margin-left:{{{margin-left|{{{margin|0}}}}}}; border-width:medium; padding:0; {{{style|}}}"
{{#if:{{{title|{{{標題|{{{标题|}}}}}} }}} |{{!}}+ '''{{{title|{{{標題|{{{标题}}}}}} }}}'''}}
{{#if:{{{noheaders|}}}{{{notitle|{{{無標題|{{{无标题|}}}}}} }}} |
|! scope="col" style="width:50%;{{{colheaderstyle|}}}{{{col1headerstyle|}}}"{{!}} {{{col1|{{{t1|-{zh-cn:代码; zh-tw:原始碼;}-}}}}}} {{!!}}<!--
-->scope="col" style="width:50%;{{{colheaderstyle|}}}{{{col2headerstyle|}}}"{{!}} {{{col2|{{{t2|效果}}}}}}
}}<!--
-->{{#if:{{{1|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{1|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{2|}}} }} }}<!--
-->{{#if:{{{3|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{3|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{4|}}} }} }}<!--
-->{{#if:{{{5|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{5|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{6|}}} }} }}<!--
-->{{#if:{{{7|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{7|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{8|}}} }} }}<!--
-->{{#if:{{{9|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{9|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{10|}}} }} }}<!--
-->{{#if:{{{11|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{11|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{12|}}} }} }}<!--
-->{{#if:{{{13|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{13|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{14|}}} }} }}<!--
-->{{#if:{{{15|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{15|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{16|}}} }} }}<!--
-->{{#if:{{{17|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{17|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{18|}}} }} }}<!--
-->{{#if:{{{19|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{19|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{20|}}} }} }}<!--
-->{{#if:{{{21|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{21|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{22|}}} }} }}<!--
-->{{#if:{{{23|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{23|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{24|}}} }} }}<!--
-->{{#if:{{{25|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{25|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{26|}}} }} }}<!--
-->{{#if:{{{27|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{27|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{28|}}} }} }}<!--
-->{{#if:{{{29|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{29|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{30|}}} }} }}<!--
-->{{#if:{{{31|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{31|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{32|}}} }} }}<!--
-->{{#if:{{{33|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{33|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{34|}}} }} }}<!--
-->{{#if:{{{35|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{35|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{36|}}} }} }}<!--
-->{{#if:{{{37|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{37|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{38|}}} }} }}<!--
-->{{#if:{{{39|}}} |{{Markup/row |c1style={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|c1={{{39|}}} |c2style={{{col2style|{{{outputstyle|}}}}}}|c2={{{40|}}} }} }}
|-
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:#ddd; padding:5px; vertical-align:top;"|
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:#ddd; padding:5px; vertical-align:top;"|
|}</includeonly><noinclude>
{{Documentation}}
</noinclude>
70675bc6fd9a1fdeb95793090bf2af75fb7b518b
Template:Markup/row
10
196
411
410
2024-08-04T12:22:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{| style="width:90%;border-width:medium;"</noinclude> 
|-
|style="width:50%; background:var(--background-color-neutral-subtle,#f9f9f9); color: inherit;border-width:1px;border-style:solid none none solid;border-color:var(--border-color-muted,#ddd); padding:9px 5px 5px; vertical-align:top;"| <!--
-->{{#tag:pre |{{{c1|[markup]}}}|style="margin:0;border:none;padding:0; word-wrap:break-word; white-space:-moz-pre-wrap;white-space:-o-pre-wrap;white-space:-pre-wrap;white-space:pre-wrap; {{{c1style|}}}"}}
|style="width:50%; background:var(--background-color-neutral-subtle,#f9f9f9); color: inherit;border-width:1px;border-style:solid solid none solid;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:top;"| <!--
--><div style="{{{c2style|}}}">
{{{c2|[''rendering'']}}}
</div>
<!--
--><noinclude>
|-
|style="width:50%;border-width:1px;border-style:solid none none none;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:text-top;"|
|style="width:50%; border-width:1px;border-style:solid none none none;border-color:var(--border-color-muted,#ddd); padding:5px; vertical-align:text-top;"|
|-
|}</noinclude>
aa743127991adfc72d644b7a5fea77723e2e9c81
Template:Esoteric
10
197
413
412
2024-08-04T12:22:19Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Intricate template]]
{{Pp-template|small=yes}}
{{Redirect category shell|1=
{{移動重定向}}
{{模板重定向}}
}}
763c8d2bf303bd0cf855c67f6c423acce73c2ac8
Template:Intricate template
10
198
415
414
2024-08-04T12:22:20Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{ombox
| type = style
| image = [[File:Ambox warning yellow.svg|40px|alt=|link=]]
| text = '''本模板含有複雜而精密的扩展语法。'''<br/><small>編輯本模板前,建議您先熟悉[[Help:解析器函数|解析器函數]]与本模板的设计思路、运作原理等。若您的編輯引發了意外的問題,請儘快[[Wikipedia:回退|撤銷]]編輯,因為本模板可能被大量頁面使用。<br/>您所作的编辑可先在<span class="nowraplinks">{{#switch:
{{#ifexist:{{FULLPAGENAME}}/sandbox |sandbox |
{{#ifexist:{{FULLPAGENAME}}/Sandbox |Sandbox |
{{#ifexist:{{FULLPAGENAME}}/test sandbox|test sandbox|
{{#ifexist:{{FULLPAGENAME}}/Test sandbox|Test sandbox|
{{#ifexist:{{FULLPAGENAME}}/test |test |
{{#ifexist:{{FULLPAGENAME}}/Test |Test |
}} }} }} }} }} }}
| sandbox = [[Template:{{PAGENAME}}/sandbox |本模板的沙盒]]
| Sandbox = [[Template:{{PAGENAME}}/Sandbox |/Sandbox子頁面]]
| test sandbox = [[Template:{{PAGENAME}}/test sandbox|/test sandbox子頁面]]
| Test sandbox = [[Template:{{PAGENAME}}/Test sandbox|/Test sandbox子頁面]]
| test = [[Template:{{PAGENAME}}/test |/test子頁面]]
| Test = [[Template:{{PAGENAME}}/Test |/Test子頁面]]
| #default = [[Template:沙盒 |模板沙盒]]
<!--ENDswitch-->}}</span>或您的[[Help:用户页|个人页面]]中进行測試。</small>
}}<includeonly>{{#ifeq: {{PAGENAME}} | {{BASEPAGENAME}} | [[Category:精密模板]] }}</includeonly><noinclude>
{{Documentation}}<!--
请将分类添加至模板文档页面,跨语言链接添加至维基数据页面。
請將分類添加至模板文件頁面,跨語言連結添加至Wikidata頁面。
--></noinclude>
b582208e633dcae9032dc9243179a7f3c21c7e11
Module:Citation/CS1/Error
828
199
417
416
2024-08-04T12:22:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[
本模块包含了与CS1模块所需,与错误/维护信息相关的函数。错误/维护信息及相关的追踪分类存放于本模块定义的表z中。
请留意过去本站及当前的英文站相应的模块中,该表曾导出供其它模块使用;现已取消。
请勿在其它模块中直接使用或操作表z。由于不兼容性,请勿直接使用英文站模块中定义、和表z有关的函数。
目前该模块导出8个函数,其中:
add_maint_cat()和add_prop_cat()分别用于向表z添加配置模块中定义的"引文格式1维护"分类和"CS1屬性"分类
set_error()和append_error()的用途都是向表z添加配置模块中定义的"引文格式1错误"分类,同时生成一条报错信息;
前者会将该条信息作为返回值输出,后者则直接将该条信息插入表z中。
主模块最后会调用make_error_tail(),在引文的尾部集中输出存储于表z的有关信息。
因此,如报错信息需显示在引文中部,应使用set_error(),并手动将其返回的报错信息插入引文中部;
如报错信息可集中显示在引文尾部,只需使用append_error()即可。
reset_error()用于清除表z中指定的信息。
select_one()用于在多个可能有效的参数中挑选一个,如多于一个参数有效会自动报"xx与yy与zz...只需其一"错误。
throw_error()产生一条配置模块中定义的"内部错误"信息,并终止程序。
]]
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local z = {
error_categories = {}; -- for categorizing citations that contain errors
error_ids = {};
message_tail = {};
maintenance_cats = {}; -- for categorizing citations that aren't erroneous per se, but could use a little work
properties_cats = {}; -- for categorizing citations based on certain properties, language of source for instance
};
local cfg;
local in_array, is_set, substitute, wrap_style;
local make_internal_link;
--[[--------------------------< T H R O W _ E R R O R >-------------------------------------------------------
Terminate the program with a pre-defined excuse.
]]
local function throw_error (arg)
error (cfg.internal_errors[arg]);
end
--[[--------------------------< E R R O R _ C O M M E N T >----------------------------------------------------
Wraps error messages with css markup according to the state of hidden.
]]
local function error_comment (content, hidden)
return wrap_style (hidden and 'hidden-error' or 'visible-error', content);
end
--[[--------------------------< S E T _ E R R O R >--------------------------------------------------------------
Sets an error condition and returns the appropriate error message. The actual placement of the error message in the output is
the responsibility of the calling function.
]]
local added_error_cats = {};
local function set_error (error_id, arguments, raw, prefix, suffix)
local error_state = cfg.error_conditions[error_id];
prefix = prefix or '';
suffix = suffix or '';
if error_state == nil then
throw_error ('undefined_error');
elseif is_set (error_state.category) then
local category = substitute (error_state.category, arguments);
if not added_error_cats[error_id] then
table.insert (z.error_categories, category)
added_error_cats[error_id] = true; -- note that we've added this category
end
end
local message = substitute (error_state.message, arguments);
message = table.concat (
{
message,
' (',
make_internal_link (
table.concat (
{
cfg.messages['help page link'],
'#',
error_state.anchor
}),
cfg.messages['help page label']),
')'
});
z.error_ids[error_id] = true;
if in_array (error_id, {'bare_url_missing_title', 'trans_missing_title'})
and z.error_ids['citation_missing_title'] then
return '', false;
end
message = table.concat ({prefix, message, suffix});
if raw == true then
return message, error_state.hidden;
end
return error_comment (message, error_state.hidden);
end
--[[--------------------------< A P P E N D _ E R R O R >--------------------------------------------------------
Sets an error condition, then appends the appropriate error message to z.message_tail.
]]
local function append_error (error_id, arguments, prefix, suffix)
table.insert (z.message_tail, {set_error (error_id, arguments, true, prefix, suffix)});
end
--[[-------------------------< I S _ A L I A S _ U S E D >-----------------------------------------------------
This function is used by select_one() to determine if one of a list of alias parameters is in the argument list
provided by the template.
Input:
args – pointer to the arguments table from calling template
alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration
index – for enumerated parameters, identifies which one
enumerated – true/false flag used to choose how enumerated aliases are examined
value – value associated with an alias that has previously been selected; nil if not yet selected
selected – the alias that has previously been selected; nil if not yet selected
error_list – list of aliases that are duplicates of the alias already selected
Returns:
value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected
selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected
]]
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)
if enumerated then -- is this a test for an enumerated parameters?
alias = alias:gsub ('#', index); -- replace '#' with the value in index
else
alias = alias:gsub ('#', ''); -- remove '#' if it exists
end
if is_set (args[alias]) then -- alias is in the template's argument list
if value ~= nil and selected ~= alias then -- if we have already selected one of the aliases
local skip;
for _, v in ipairs (error_list) do -- spin through the error list to see if we've added this alias
if v == alias then
skip = true;
break; -- has been added so stop looking
end
end
if not skip then -- has not been added so
table.insert (error_list, alias); -- add error alias to the error list
end
else
value = args[alias]; -- not yet selected an alias, so select this one
selected = alias;
end
end
return value, selected; -- return newly selected alias, or previously selected alias
end
--[[--------------------------< A D D _ M A I N T _ C A T >------------------------------------------------------
Adds a category to z.maintenance_cats using names from the configuration file with additional text if any.
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maintenance_cats.
]]
local added_maint_cats = {};
local function add_maint_cat (key, arguments)
if not added_maint_cats [key] then
added_maint_cats [key] = true; -- note that we've added this category
table.insert (z.maintenance_cats, substitute (cfg.maint_cats [key], arguments));
-- make name then add to table
end
end
--[[--------------------------< A D D _ P R O P _ C A T >--------------------------------------------------------
Adds a category to z.properties_cats using names from the configuration file with additional text if any.
]]
local added_prop_cats = {} -- list of property categories that have been added to z.properties_cats
local function add_prop_cat (key, arguments)
if not added_prop_cats [key] then
added_prop_cats [key] = true; -- note that we've added this category
table.insert (z.properties_cats, substitute (cfg.prop_cats [key], arguments));
-- make name then add to table
end
end
--[[--------------------------< S E L E C T _ O N E >----------------------------------------------------------
Chooses one matching parameter from a list of parameters to consider. The list of parameters to consider is just
names. For parameters that may be enumerated, the position of the numerator in the parameter name is identified
by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'.
Because enumerated parameter |<param>1= is an alias of |<param>= we must test for both possibilities.
Generates an error if more than one match is present.
]]
local function select_one (args, aliases_list, error_condition, index)
local value = nil; -- the value assigned to the selected parameter
local selected = ''; -- the name of the parameter we have chosen
local error_list = {};
if index ~= nil then index = tostring (index); end
for _, alias in ipairs (aliases_list) do -- for each alias in the aliases list
if alias:match ('#') then -- if this alias can be enumerated
if '1' == index then -- when index is 1 test for enumerated and non-enumerated aliases
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); -- first test for non-enumerated alias
end
value, selected = is_alias_used (args, alias, index, true, value, selected, error_list); -- test for enumerated alias
else
value, selected = is_alias_used (args, alias, index, false, value, selected, error_list); --test for non-enumerated alias
end
end
if #error_list > 0 and 'none' ~= error_condition then -- for cases where this code is used outside of extract_names()
local error_str = '';
for _, k in ipairs (error_list) do
if error_str ~= '' then error_str = error_str .. cfg.messages['parameter-separator'] end
error_str = error_str .. wrap_style ('parameter', k);
end
if #error_list > 1 then
error_str = error_str .. cfg.messages['parameter-final-separator'];
else
error_str = error_str .. cfg.messages['parameter-pair-separator'];
end
error_str = error_str .. wrap_style ('parameter', selected);
append_error (error_condition, {error_str});
end
return value, selected;
end
--[[--------------------------< M A K E _ E R R O R _ T A I L >--------------------------------------------------
The function generates error/maintenance-related messages and/or tracking categories from "z" defined in this module.
]]
local function make_error_tail (flag)
local error_text = '';
if #z.message_tail ~= 0 then
error_text = ' ';
for i,v in ipairs (z.message_tail) do
if is_set (v[1]) then
if i == #z.message_tail then
error_text = error_text .. error_comment (v[1], v[2]);
else
error_text = error_text .. error_comment (v[1] .. '; ', v[2]);
end
end
end
end
if #z.maintenance_cats ~= 0 then
local maintenance_text = '';
for _, v in ipairs (z.maintenance_cats) do -- append maintenance categories
maintenance_text = maintenance_text .. substitute (cfg.messages['maintenance-item'], {v, make_internal_link (':Category:' .. v, cfg.messages['maintenance-link'])})
end
error_text = error_text .. wrap_style ('maintenance', maintenance_text);
-- maintenance mesages (realy just the names of the categories for now)
end
if not flag then
for _, v in ipairs (z.error_categories) do
error_text = error_text .. make_internal_link ('Category:' .. v);
end
for _, v in ipairs (z.maintenance_cats) do -- append maintenance categories
error_text = error_text .. make_internal_link ('Category:' .. v);
end
for _, v in ipairs (z.properties_cats) do -- append maintenance categories
error_text = error_text .. make_internal_link ('Category:' .. v);
end
end
return error_text;
end
--[[--------------------------< R E S E T _ E R R O R >-------------------------------------------------------
Reset error/maintenance messages/categories in z.
]]
local function reset_error (args)
if (in_array ('err_cats', args)) then
z.error_categories = {};
end
if (in_array ('prop_cats', args)) then
z.properties_cats = {};
end
if (in_array ('maint_cats', args)) then
z.maintenance_cats = {};
end
if (in_array ('err_ids', args)) then
z.error_ids = {};
end
if (in_array ('msg_tail', args)) then
z.message_tail = {};
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
in_array = utilities_page_ptr.in_array;
is_set = utilities_page_ptr.is_set;
substitute = utilities_page_ptr.substitute;
wrap_style= utilities_page_ptr.wrap_style;
make_internal_link = links_page_ptr.make_internal_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
add_maint_cat = add_maint_cat, -- exported functions
add_prop_cat = add_prop_cat,
append_error = append_error,
make_error_tail = make_error_tail,
reset_error = reset_error,
select_one = select_one,
set_error = set_error,
throw_error = throw_error,
set_selected_modules = set_selected_modules
}
72c70434eb1bad858e4ea121f07809f6cb76c9f9
Module:Citation/CS1/Links
828
200
419
418
2024-08-04T12:22:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[
本模块用于处理维基内链和外链。目前导出四个函数:
check_for_external_link()用于批量检查参数中可能存在的外链。
make_external_link()依据输入的url参数和"显示"参数输出维基外链,
并对其中url参数的格式进行检查。若查出url格式不正确,
在设定"源"参数的情况下,会根据该参数产生"引文格式1错误"信息,
附于生成的外链后方;如"源"参数未设定,则会抛出内部错误终止程序。
make_internal_link()依据输入的"目标页面"参数和"显示"参数输出维基内链,
并对其中"目标页面"参数的格式稍加检查。
若查出"目标页面"格式不正确(例如:含有页面标题中不允许出现的字符),
在设定"源"参数的情况下,会根据该参数产生"引文格式1错误"信息,
该条信息被其它模块处理后会显示于引文的尾部;
如"源"参数未设定,则会抛出内部错误终止程序。
以上两个函数既可用于处理模板参数,也可用于转换配置模块中的有关参数。
但请注意,用于前者时必须指定"源"参数(即被处理的参数名称)并保证其值有效,
用于后者时必须确保配置文件模块编写正确。否则将导致Lua错误!
remove_wiki_link()用于移除维基内链。
]]
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set;
local append_error, set_error, throw_error;
--[[--------------------------< I S _ S C H E M E >------------------------------------------------------------
does this thing that purports to be a uri scheme seem to be a valid scheme? The scheme is checked to see if it
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:
Scheme names consist of a sequence of characters beginning with a
letter and followed by any combination of letters, digits, plus
("+"), period ("."), or hyphen ("-").
returns true if it does, else false
]]
local function is_scheme (scheme)
return scheme and scheme:match ('^%a[%a%d%+%.%-]*:'); -- true if scheme is set and matches the pattern
end
--[=[-------------------------< I S _ D O M A I N _ N A M E >--------------------------------------------------
Does this thing that purports to be a domain name seem to be a valid domain name?
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5
BNF defined here: https://tools.ietf.org/html/rfc4234
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;
see also [[Single-letter second-level domain]]
list of tlds: https://www.iana.org/domains/root/db
rfc952 (modified by rfc 1123) requires the first and last character of a hostname to be a letter or a digit. Between
the first and last characters the name may use letters, digits, and the hyphen.
Also allowed are IPv4 addresses. IPv6 not supported
domain is expected to be stripped of any path so that the last character in the last character of the tld. tld
is two or more alpha characters. Any preceding '//' (from splitting a url with a scheme) will be stripped
here. Perhaps not necessary but retained incase it is necessary for IPv4 dot decimal.
There are several tests:
the first character of the whole domain name including subdomains must be a letter or a digit
single-letter/digit second-level domains in the .org TLD
q, x, and z SL domains in the .com TLD
i and q SL domains in the .net TLD
single-letter SL domains in the ccTLDs (where the ccTLD is two letters)
two-character SL domains in gTLDs (where the gTLD is two or more letters)
three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)
IPv4 dot-decimal address format; TLD not allowed
returns true if domain appears to be a proper name and tld or IPv4 address, else false
]=]
local function is_domain_name (domain)
if not domain then
return false; -- if not set, abandon
end
domain = domain:gsub ('^//', ''); -- strip '//' from domain name if present; done here so we only have to do it once
if not domain:match ('^[%a%d]') then -- first character must be letter or digit
return false;
end
if domain:match ('%f[%a%d][%a%d]%.org$') then -- one character .org hostname
return true;
elseif domain:match ('%f[%a][qxz]%.com$') then -- assigned one character .com hostname (x.com times out 2015-12-10)
return true;
elseif domain:match ('%f[%a][iq]%.net$') then -- assigned one character .net hostname (q.net registered but not active 2015-12-10)
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$') then -- internationalized domain name with ACE prefix
return true;
elseif domain:match ('%f[%a%d][%a%d]%.cash$') then -- one character/digit .cash hostname
return true;
elseif domain:match ('%f[%a%d][%a%d]%.%a%a$') then -- one character hostname and cctld (2 chars)
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d]%.%a%a+$') then -- two character hostname and tld
return true;
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.%a%a+$') then -- three or more character hostname.hostname or hostname.tld
return true;
elseif domain:match ('^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?') then -- IPv4 address
return true;
else
return false;
end
end
--[[--------------------------< I S _ U R L >------------------------------------------------------------------
returns true if the scheme and domain parts of a url appear to be a valid url; else false.
This function is the last step in the validation process. This function is separate because there are cases that
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external
wikilinks.
]]
local function is_url (scheme, domain)
if is_set (scheme) then -- if scheme is set check it and domain
return is_scheme (scheme) and is_domain_name (domain);
else
return is_domain_name (domain); -- scheme not set when url is protocol relative
end
end
--[[--------------------------< S P L I T _ U R L >------------------------------------------------------------
Split a url into a scheme, authority indicator, and domain.
If protocol relative url, return nil scheme and domain else return nil for both scheme and domain.
When not protocol relative, get scheme, authority indicator, and domain. If there is an authority indicator (one
or more '/' characters following the scheme's colon), make sure that there are only 2.
]]
local function split_url (url_str)
local scheme, authority, domain;
url_str = url_str:gsub ('([%a%d])%.?[/%?#].*$', '%1'); -- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of '//')
if url_str:match ('^//%S*') then -- if there is what appears to be a protocol relative url
domain = url_str:match ('^//(%S*)')
elseif url_str:match ('%S-:/*%S+') then -- if there is what appears to be a scheme, optional authority indicator, and domain name
scheme, authority, domain = url_str:match ('(%S-:)(/*)(%S+)'); -- extract the scheme, authority indicator, and domain portions
authority = authority:gsub ('//', '', 1); -- replace place 1 pair of '/' with nothing;
if is_set(authority) then -- if anything left (1 or 3+ '/' where authority should be) then
return scheme; -- return scheme only making domain nil which will cause an error message
end
domain = domain:gsub ('(%a):%d+', '%1'); -- strip port number if present
end
return scheme, domain;
end
--[[--------------------------< L I N K _ P A R A M _ O K >---------------------------------------------------
checks the content of |title-link=, |series-link=, |author-link= etc for properly formatted content: no wikilinks, no urls
Link parameters are to hold the title of a wikipedia article so none of the WP:TITLESPECIALCHARACTERS are allowed:
# < > [ ] | { } _
except the underscore which is used as a space in wiki urls and # which is used for section links
returns false when the value contains any of these characters.
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid url (the
|<param>-link= parameter is ok); else false when value appears to be a valid url (the |<param>-link= parameter is NOT ok).
]]
local function link_param_ok (value)
local scheme, domain;
if value:find ('[<>%[%]|{}]') then -- if any prohibited characters
return false;
end
scheme, domain = split_url (value); -- get scheme or nil and domain or nil from url;
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid url
end
--[=[-------------------------< M A K E _ I N T E R N A L _ L I N K >------------------------------------------
Format a wikilink with error checking; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only
link is provided (or link and display are the same), returns a wikilink in the form [[L]].
]=]
local function make_internal_link (link, display, source)
if not link_param_ok (link) then
if is_set (source) then
append_error ('bad_paramlink', {source});
else
throw_error('bad_link_no_origin');
end
end
if is_set (display) and link ~= display then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
end
--[=[-------------------------< R E M O V E _ W I K I _ L I N K >----------------------------------------------
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label
if str was wrapped in wikilink markup. Presumably, this is because without wikimarkup in str, there is no match
in the initial gsub, the replacement function l() doesn't get called.
]=]
local function remove_wiki_link (str)
return (str:gsub ("%[%[([^%[%]]*)%]%]", function(l)
return l:gsub ("^[^|]*|(.*)$", "%1" ):gsub ("^%s*(.-)%s*$", "%1");
end));
end
--[=[-------------------------< I S _ W I K I L I N K >--------------------------------------------------------
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.
If str is a complex wikilink ([[L|D]]):
returns wl_type 2 and D and L from [[L|D]];
if str is a simple wikilink ([[D]])
returns wl_type 1 and D from [[D]] and L as empty string;
if not a wikilink:
returns wl_type 0, str as D, and L as empty string.
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).
]=]
local function is_wikilink (str)
local D, L
local wl_type = 2; -- assume that str is a complex wikilink [[L|D]]
if not str:match ('^%[%[[^%]]+%]%]$') then -- is str some sort of a wikilink (must have some sort of content)
return 0, str, ''; -- not a wikilink; return wl_type as 0, str as D, and empty string as L
end
L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$'); -- get L and D from [[L|D]]
if not is_set (D) then -- if no separate display
D = str:match ('^%[%[([^%]]*)|*%]%]$'); -- get D from [[D]] or [[D|]]
wl_type = 1;
end
D = mw.text.trim (D, '%s|'); -- trim white space and pipe characters
return wl_type, D, L or '';
end
--[[--------------------------< S A F E _ F O R _ U R L >------------------------------------------------------
Escape sequences for content that will be used for URL descriptions
]]
local function safe_for_url( str )
if str:match( "%[%[.-%]%]" ) ~= nil then
append_error( 'wikilink_in_url', {});
end
return str:gsub( '[%[%]\n]', {
['['] = '[',
[']'] = ']',
['\n'] = ' ' } );
end
--[[--------------------------< C H E C K _ U R L >------------------------------------------------------------
Determines whether a URL string appears to be valid.
First we test for space characters. If any are found, return false. Then split the url into scheme and domain
portions, or for protocol relative (//example.com) urls, just the domain. Use is_url() to validate the two
portions of the url. If both are valid, or for protocol relative if domain is valid, return true, else false.
]]
local function check_url( url_str )
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value it can't be a proper url
return false;
end
local scheme, domain;
scheme, domain = split_url (url_str); -- get scheme or nil and domain or nil from url;
return is_url (scheme, domain); -- return true if value appears to be a valid url
end
--[[--------------------------< M A K E _ E X T E R N A L _ L I N K >--------------------------------------------
Format an external link with error checking
]]
local function make_external_link( URL, label, source )
local error_str = "";
if not is_set( label ) then
label = URL;
if is_set( source ) then
error_str = set_error( 'bare_url_missing_title', source, false, " " );
else
throw_error( 'bare_url_no_origin' );
end
end
if not check_url( URL ) then
if is_set ( source ) then
error_str = set_error( 'bad_url', source, false, " " ) .. error_str;
else
throw_error( 'bad_url_no_origin' );
end
end
return table.concat({ "[", URL, " ", safe_for_url( label ), "]", error_str });
end
--[=[-------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
non-space characters following the opening bracket appear to be a url. The test will also find external wikilinks
that use protocol relative urls. Also finds bare urls.
The frontier pattern prevents a match on interwiki links which are similar to scheme:path urls. The tests that
find bracketed urls are required because the parameters that call this test (currently |title=, |chapter=, |work=,
and |publisher=) may have wikilinks and there are articles or redirects like '//Hus' so, while uncommon, |title=[[//Hus]]
is possible as might be [[en://Hus]].
]=]
local function is_parameter_ext_wikilink (value)
local scheme, domain;
value = value:gsub ('([^%s/])/[%a%d].*', '%1'); -- strip path information (the capture prevents false replacement of '//')
if value:match ('%f[%[]%[%a%S*:%S+.*%]') then -- if ext wikilink with scheme and domain: [xxxx://yyyyy.zzz]
scheme, domain = value:match ('%f[%[]%[(%a%S*:)(%S+).*%]')
elseif value:match ('%f[%[]%[//%S*%.%S+.*%]') then -- if protocol relative ext wikilink: [//yyyyy.zzz]
domain = value:match ('%f[%[]%[//(%S*%.%S+).*%]');
elseif value:match ('%a%S*:%S+') then -- if bare url with scheme; may have leading or trailing plain text
scheme, domain = value:match ('(%a%S*:)(%S+)');
elseif value:match ('//%S*%.%S+') then -- if protocol relative bare url: //yyyyy.zzz; may have leading or trailing plain text
domain = value:match ('//(%S*%.%S+)'); -- what is left should be the domain
else
return false; -- didn't find anything that is obviously a url
end
return is_url (scheme, domain); -- return true if value appears to be a valid url
end
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
loop through a list of parameters and their values. Look at the value and if it has an external link, emit an error message.
]]
local function check_for_external_link (parameter_list)
local error_message = '';
for k, v in pairs (parameter_list) do -- for each parameter in the list
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a url add an error message
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "|" .. k .. "="; -- add the failed parameter
end
end
if is_set (error_message) then -- done looping, if there is an error message, display it
append_error( 'param_has_ext_link', {error_message});
end
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Import some functions from Module:Citation/CS1/Utilities and Module:Citation/CS1/Error
]]
local function set_selected_modules (utilities_page_ptr, error_page_ptr)
is_set = utilities_page_ptr.is_set;
append_error = error_page_ptr.append_error;
set_error = error_page_ptr.set_error;
throw_error = error_page_ptr.throw_error;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
check_for_external_link = check_for_external_link, -- exported functions
make_external_link = make_external_link,
make_internal_link = make_internal_link,
remove_wiki_link = remove_wiki_link,
set_selected_modules = set_selected_modules
}
662c9e35ee3704a0dda91f09654ce9e41fbeb9a4
Module:Citation/CS1/Language
828
201
421
420
2024-08-04T12:22:21Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, wrap_msg, wrap_style;
local add_prop_cat, add_maint_cat;
--[[--------------------------< L O C A L _ T A B L E >-------------------------------------------------------
]]
local local_table = {
['abe']= '西阿贝纳基语',
['abq']= '阿巴扎语',
['abq-latn']= '阿巴扎语(拉丁文字)',
['abs']= '安汶马来语',
['ady-cyrl']= '阿迪格语(西里尔文)',
['aeb-arab']= '突尼斯阿拉伯语(阿拉伯文字)',
['aeb-latn']= '突尼斯阿拉伯语(拉丁文字)',
['alc']= '阿拉卡卢夫语',
['ami']= '阿美语',
['azb']= '南阿塞拜疆语',
['bat-smg']= '萨莫吉希亚语',
['bbc-latn']= '多巴巴塔克语(拉丁文字)',
['bcc']= '南俾路支语',
['bcl']= '中比科尔语',
['bdr']= '西海岸巴瑶语',
['be-tarask']= '白俄罗斯语(传统正写法)',
['be-x-old']= '白俄罗斯语(传统正写法)',
['bgp']= '东俾路支语',
['bh']='博杰普尔语',
['bxr']='俄罗斯布里亚特语',
['cja']='西部占语',
['cja-arab']='西部占语(阿拉伯文字)',
['cja-cham']='西部占语(阿拉伯文字)',
['cja-latn']='西部占语(拉丁文字)',
['cjm']='东部占语',
['cjm-arab']='东部占语(阿拉伯文字)',
['cjm-cham']='东部占语(阿拉伯文字)',
['cjm-latn']='东部占语(拉丁文字)',
['cjy']='晋语',
['cjy-hans']='晋语(简体)',
['cjy-hant']='晋语(繁体)',
['ckt']='楚科奇语',
['en-in']= '印度英语',
['ike-cans']='东加拿大语(原住民音节)',
['ike-latn']='东加拿大语(拉丁文字)',
['ruq']='梅格莱诺-罗马尼亚语',
['ruq-cyrl']='梅格列诺-罗马尼亚语(西里尔文字)',
['ruq-grek']='梅格列诺-罗马尼亚语(希腊文字)',
['ruq-latn']='梅格列诺-罗马尼亚语(拉丁文字)',
['cdo']= '闽东语',
['cdo-hani']= '闽东语(汉字)',
['ja-hani'] = '日语(汉字文字)',
['ja-hira'] = '日语(平假名文字)',
['ja-hrkt'] = '日语(假名文字)',
['ja-kana'] = '日语(片假名文字)',
['ko-kp'] = '朝鲜朝鲜语',
['kk-cn'] = '中国哈萨克语',
['no'] = '挪威语',
['ojp'] = '古日语',
['ojp-hani'] = '古日语(汉字文字)',
['ojp-hira'] = '古日语(平假名文字)',
['tet'] = '德顿语',
['ug-arab'] = '维吾尔语(阿拉伯文字)',
['ug-latn'] = '维吾尔语(拉丁文字)',
-- ['zh-cn'] = '中国大陆中文',
-- ['zh-hans'] = '简体中文',
-- ['zh-hant'] = '繁體中文',
-- ['zh-hk'] = '香港中文',
['zh-min-nan'] = '闽南语',
-- ['zh-mo'] = '澳門中文',
-- ['zh-my'] = '马来西亚中文',
-- ['zh-sg'] = '新加坡中文',
-- ['zh-tw'] = '臺灣中文',
}
local function fetchLocalLanguageName (code)
return local_table[code];
end
--[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >----------------------------------------
|script-title= holds title parameters that are not written in Latin based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should
not be italicized and may be written right-to-left. The value supplied by |script-title= is concatenated onto Title after Title has been wrapped
in italic markup.
Regardless of language, all values provided by |script-title= are wrapped in <bdi>...</bdi> tags to isolate rtl languages from the English left to right.
|script-title= provides a unique feature. The value in |script-title= may be prefixed with a two-character ISO639-1 language code and a colon:
|script-title=ja:*** *** (where * represents a Japanese character)
Spaces between the two-character code and the colon and the colon and the first script character are allowed:
|script-title=ja : *** ***
|script-title=ja: *** ***
|script-title=ja :*** ***
Spaces preceding the prefix are allowed: |script-title = ja:*** ***
The prefix is checked for validity. If it is a valid ISO639-1 language code, the lang attribute (lang="ja") is added to the <bdi> tag so that browsers can
know the language the tag contains. This may help the browser render the script more correctly. If the prefix is invalid, the lang attribute
is not added. At this time there is no error message for this condition.
Supports |script-title= and |script-chapter=
TODO: error messages when prefix is invalid ISO639-1 code; when script_value has prefix but no script;
]]
local function format_script_value (script_value)
local lang=''; -- initialize to empty string
local name;
if script_value:match('^%l%l%s*:') then -- if first 3 non-space characters are script language prefix
lang = script_value:match('^(%l%l)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script
if not is_set (lang) then
return ''; -- script_value was just the prefix so return empty string
end
-- if we get this far we have prefix and script
name = mw.language.fetchLanguageName( lang, mw.getContentLanguage():getCode() ); -- get language name so that we can use it to categorize
if is_set (name) then -- is prefix a proper ISO 639-1 language code?
script_value = script_value:gsub ('^%l%l%s*:%s*', ''); -- strip prefix from script
-- is prefix one of these language codes?
if in_array (lang, {'ar', 'bg', 'bs', 'dv', 'el', 'fa', 'he', 'hy', 'ja', 'ka', 'ko', 'ku', 'mk', 'ps', 'ru', 'sd', 'sr', 'th', 'uk', 'ug', 'yi', 'zh'}) then
add_prop_cat ('script_with_name', {name, lang})
else
add_prop_cat ('script')
end
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute
else
lang = ''; -- invalid so set lang to empty string
end
end
if is_set(script_value) then
script_value = '-{R|' .. script_value .. '}-';
end
script_value = wrap_style('bdi', {lang, script_value}); -- isolate in case script is rtl
return script_value;
end
--[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script value has been
wrapped in <bdi> tags.
]]
local function script_concatenate (title, script)
if is_set(title) then
title = '-{R|' .. title .. '}-';
end
if is_set (script) then
script = format_script_value (script); -- <bdi> tags, lang atribute, categorization, etc; returns empty string on error
if is_set (script) then
title = title .. ' ' .. script; -- concatenate title and script title
end
end
return title;
end
--[[--------------------------< G E T _ I S O 6 3 9 _ C O D E >------------------------------------------------
Validates language names provided in |language= parameter if not an ISO639-1 code. Handles the special case that is Norwegian where
ISO639-1 code 'no' is mapped to language name 'Norwegian Bokmål' by Extention:CLDR.
Returns the language name and associated ISO639-1 code. Because case of the source may be incorrect or different from the case that Wikimedia
uses, the name comparisons are done in lower case and when a match is found, the Wikimedia version (assumed to be correct) is returned along
with the code. When there is no match, we return the original language name string.
mw.language.fetchLanguageNames() will return a list of languages that aren't part of ISO639-1. Names that aren't ISO639-1 but that are included
in the list will be found if that name is provided in the |language= parameter. For example, if |language=Samaritan Aramaic, that name will be
found with the associated code 'sam', not an ISO639-1 code. When names are found and the associated code is not two characters, this function
returns only the Wikimedia language name.
Adapted from code taken from Module:Check ISO 639-1.
]]
local function get_iso639_code (lang)
if 'norwegian' == lang:lower() then -- special case related to Wikimedia remap of code 'no' at Extension:CLDR
return '挪威语', 'no'; -- Make sure rendered version is properly capitalized
end
local languages = mw.language.fetchLanguageNames (mw.getContentLanguage():getCode(), 'all') -- get a list of language names known to Wikimedia
-- ('all' is required for North Ndebele, South Ndebele, and Ojibwa)
local langlc = mw.ustring.lower (lang); -- lower case version for comparisons
for code, name in pairs (languages) do -- scan the list to see if we can find our language
if langlc == mw.ustring.lower (name) then
if 2 ~= code:len() then -- ISO639-1 codes only
return name; -- so return the name but not the code
end
return name, code; -- found it, return name to ensure proper capitalization and the ISO639-1 code
end
end
return lang; -- not valid language; return language in original case and nil for ISO639-1 code
end
--[[--------------------------< L A N G U A G E _ P A R A M E T E R >------------------------------------------
Get language name from ISO639-1 code value provided. If a code is valid use the returned name; if not, then use the value that was provided with the language parameter.
There is an exception. There are three ISO639-1 codes for Norewegian language variants. There are two official variants: Norwegian Bokmål (code 'nb') and
Norwegian Nynorsk (code 'nn'). The third, code 'no', is defined by ISO639-1 as 'Norwegian' though in Norway this is pretty much meaningless. However, it appears
that on enwiki, editors are for the most part unaware of the nb and nn variants (compare page counts for these variants at Category:Articles with non-English-language external links.
Because Norwegian Bokmål is the most common language variant, Media wiki has been modified to return Norwegian Bokmål for ISO639-1 code 'no'. Here we undo that and
return 'Norwegian' when editors use |language=no. We presume that editors don't know about the variants or can't descriminate between them.
See Help talk:Citation Style_1#An ISO 639-1 language name test
When |language= contains a valid ISO639-1 code, the page is assigned to the category for that code: Category:Norwegian-language sources (no) if
the page is a mainspace page and the ISO639-1 code is not 'en'. Similarly, if the parameter is |language=Norwegian, it will be categorized in the same way.
This function supports multiple languages in the form |language=nb, French, th where the language names or codes are separated from each other by commas.
]]
local function language_parameter (lang)
local code; -- the ISO639-1 two character code
local name; -- the language name
local language_list = {}; -- table of language names to be rendered
local names_table = {}; -- table made from the value assigned to |language=
if not is_set (lang) then
return '';
end
names_table = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list
for _, lang in ipairs (names_table) do -- reuse lang
name = fetchLocalLanguageName (lang:lower()); -- local table first
if not is_set (name) then
if lang:match ('^%a%a%-') or 2 == lang:len() then -- ISO639-1 language code are 2 characters (fetchLanguageName also supports 3 character codes)
if lang:match ('^zh-') then
name = mw.language.fetchLanguageName (lang:lower(), lang:lower());
else
if not is_set (name) then
name = mw.language.fetchLanguageName (lang:lower(), mw.getContentLanguage():getCode());
-- get ISO 639-1 language name if Language is a proper code
end
end
end
end
if is_set (name) then -- if Language specified a valid ISO639-1 code
code = lang:lower(); -- save it
else
name, code = get_iso639_code (lang); -- attempt to get code from name (assign name here so that we are sure of proper capitalization)
end
if is_set (code) then
if 'zh' ~= code and not code:match ('^zh-') then -- Chinese not the language
add_prop_cat ('foreign_lang_source', {name, code})
end
else
add_maint_cat ('unknown_lang'); -- add maint category if not already added
end
table.insert (language_list, name);
name = ''; -- so we can reuse it
end
code = #language_list -- reuse code as number of languages in the list
if 2 >= code then
name = table.concat (language_list, '及') -- insert '及' between two language names
elseif 2 < code then
language_list[code] = '及' .. language_list[code]; -- prepend last name with '及'
name = table.concat (language_list, '、'); -- and concatenate with '<comma><space>' separators
name = name:gsub ('、及', '及', 1);
end
return (" " .. wrap_msg ('language', name)); -- otherwise wrap with '(in ...)'
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
]]
local function set_selected_modules (utilities_page_ptr, error_page_ptr)
is_set = utilities_page_ptr.is_set; -- import functions from selected Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array;
wrap_style = utilities_page_ptr.wrap_style;
wrap_msg = utilities_page_ptr.wrap_msg;
add_prop_cat = error_page_ptr.add_prop_cat; -- import functions from selected Module:Citation/CS1/Error module
add_maint_cat = error_page_ptr.add_maint_cat;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
script_concatenate = script_concatenate,
language_parameter =language_parameter,
set_selected_modules = set_selected_modules
}
b9ee021194332f453ba7b48e49bd8e32553dc741
Template:Dummy ref
10
202
423
422
2024-08-04T12:22:22Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Dummy reference]]
46141c3444bc34175c04cdf7f5271ca92bcb2a8e
Template:Dummy reference
10
203
425
424
2024-08-04T12:22:22Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<sup class="reference nowrap" style="color:#002bb8;">{{#if:{{{link|}}}|[[#{{{link}}}|[{{{1|1}}}]]]|[{{{1|1}}}]}}</sup><noinclude>{{documentation}}</noinclude>
5fa04498a061148cc83f93ef0d7c0e633c5e0f09
Module:Citation/CS1/People
828
204
427
426
2024-08-04T12:22:22Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local cfg;
local in_array, is_set;
local append_error, add_maint_cat, select_one;
local make_internal_link;
--[[--------------------------< A D D _ V A N C _ E R R O R >----------------------------------------------------
Adds a single Vancouver system error message to the template's output regardless of how many error actually exist.
To prevent duplication, added_vanc_errs is nil until an error message is emitted.
]]
local added_vanc_errs = false; -- flag so we only emit one Vancouver error / category
local function add_vanc_error ()
if not added_vanc_errs then
added_vanc_errs = true; -- note that we've added this category
append_error( 'vancouver', {});
end
end
--[[--------------------------< I S _ G O O D _ V A N C _ N A M E >--------------------------------------------
For Vancouver Style, author/editor names are supposed to be rendered in Latin (read ASCII) characters. When a name
uses characters that contain diacritical marks, those characters are to converted to the corresponding Latin character.
When a name is written using a non-Latin alphabet or logogram, that name is to be transliterated into Latin characters.
These things are not currently possible in this module so are left to the editor to do.
This test allows |first= and |last= names to contain any of the letters defined in the four Unicode Latin character sets
[http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A
[http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF
[http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F
[http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F
|lastn= also allowed to contain hyphens, spaces, and apostrophes. (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
|firstn= also allowed to contain hyphens, spaces, apostrophes, and periods
At the time of this writing, I had to write the 'if nil == mw.ustring.find ...' test ouside of the code editor and paste it here
because the code editor gets confused between character insertion point and cursor position.
]]
local function is_good_vanc_name (last, first)
if nil == mw.ustring.find (last, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%']*$") or nil == mw.ustring.find (first, "^[A-Za-zÀ-ÖØ-öø-ƿDŽ-ɏ%-%s%'%.]*$") then
add_vanc_error ();
return false; -- not a string of latin characters; Vancouver required Romanization
end;
return true;
end
--[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------
Attempts to convert names to initials in support of |name-list-format=vanc.
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/.
Vancouver style requires family rank designations (Jr, II, III, etc) to be rendered as Jr, 2nd, 3rd, etc. This form is not
currently supported by this code so correctly formed names like Smith JL 2nd are converted to Smith J2. See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/.
This function uses ustring functions because firstname initials may be any of the unicode Latin characters accepted by is_good_vanc_name ().
]]
local function reduce_to_initials(first)
if mw.ustring.match(first, "^%u%u$") then return first end; -- when first contains just two upper-case letters, nothing to do
local initials = {}
local i = 0; -- counter for number of initials
for word in mw.ustring.gmatch(first, "[^%s%.%-]+") do -- names separated by spaces, hyphens, or periods
table.insert(initials, mw.ustring.sub(word,1,1)) -- Vancouver format does not include full stops.
i = i + 1; -- bump the counter
if 2 <= i then break; end -- only two initials allowed in Vancouver system; if 2, quit
end
return table.concat(initials) -- Vancouver format does not include spaces.
end
--[[--------------------------< L I S T _ P E O P L E >-------------------------------------------------------
Formats a list of people (e.g. authors / editors)
]]
local function list_people(control, people, etal, list_name) -- TODO: why is list_name here? not used in this function
local sep;
local namesep;
local format = control.format
local maximum = control.maximum
local lastauthoramp = control.lastauthoramp;
local text = {}
if 'vanc' == format then -- Vancouver-like author/editor name styling?
sep = ','; -- name-list separator between authors is a comma
namesep = ' '; -- last/first separator is a space
else
sep = ';' -- name-list separator between authors is a semicolon
namesep = ', ' -- last/first separator is <comma><space>
end
if sep:sub(-1,-1) ~= " " then sep = sep .. " " end
if is_set (maximum) and maximum < 1 then return "", 0; end -- returned 0 is for EditorCount; not used for authors
for i,person in ipairs(people) do
if is_set(person.last) then
local mask = person.mask
local one
local sep_one = sep;
if is_set (maximum) and i > maximum then
etal = true;
break;
elseif (mask ~= nil) then
local n = tonumber(mask)
if (n ~= nil) then
one = string.rep("—",n)
else
one = mask;
sep_one = " ";
end
else
one = person.last
local first = person.first
if is_set(first) then
if ( "vanc" == format ) then -- if vancouver format
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)
if not person.corporate and is_good_vanc_name (one, first) then -- and name is all Latin characters; corporate authors not tested
first = reduce_to_initials(first) -- attempt to convert first name(s) to initials
end
end
one = one .. namesep .. first
end
if is_set(person.link) and person.link ~= control.page_name then
one = make_internal_link(person.link, one, person.origin); -- link author/editor if this page is not the author's/editor's page
end
end
table.insert( text, one )
table.insert( text, sep_one )
end
end
local count = #text / 2; -- (number of names + number of separators) divided by 2
if count > 0 then
if count > 1 and is_set(lastauthoramp) and not etal then
text[#text-2] = " & "; -- replace last separator with ampersand text
end
text[#text] = nil; -- erase the last separator
end
local result = table.concat(text) -- construct list
if etal and is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've go a last-first list and etal so add et al.
end
return result, count
end
--[[--------------------------< G E T _ D I S P L A Y _ A U T H O R S _ E D I T O R S >------------------------
Returns a number that may or may not limit the length of the author or editor name lists.
When the value assigned to |display-authors= is a number greater than or equal to zero, return the number and
the previous state of the 'etal' flag (false by default but may have been set to true if the name list contains
some variant of the text 'et al.').
When the value assigned to |display-authors= is the keyword 'etal', return a number that is one greater than the
number of authors in the list and set the 'etal' flag true. This will cause the list_people() to display all of
the names in the name list followed by 'et al.'
In all other cases, returns nil and the previous state of the 'etal' flag.
]]
local function get_display_authors_editors (max, count, list_name, etal)
if is_set (max) then
if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings
max = count + 1; -- number of authors + 1 so display all author name plus et al.
etal = true; -- overrides value set by extract_names()
elseif max:match ('^%d+$') then -- if is a string of numbers
max = tonumber (max); -- make it a number
if max >= count and 'authors' == list_name then -- AUTHORS ONLY -- if |display-xxxxors= value greater than or equal to number of authors/editors
add_maint_cat ('disp_auth_ed', list_name);
end
else -- not a valid keyword or number
append_error( 'invalid_param_val', {'display-' .. list_name, max});
-- add error message
max = nil; -- unset
end
elseif 'authors' == list_name then -- AUTHORS ONLY need to clear implicit et al category
max = count + 1; -- number of authors + 1
end
return max, etal;
end
--[[--------------------------< N A M E _ H A S _ E T A L >----------------------------------------------------
Evaluates the content of author and editor name parameters for variations on the theme of et al. If found,
the et al. is removed, a flag is set to true and the function returns the modified name and the flag.
This function never sets the flag to false but returns it's previous state because it may have been set by
previous passes through this function or by the parameters |display-authors=etal or |display-editors=etal
]]
local function name_has_etal (name, etal, nocat)
if is_set (name) then -- name can be nil in which case just return
local etal_pattern = "[;,]? *[\"']*%f[%a][Ee][Tt] *[Aa][Ll][%.\"']*$" -- variations on the 'et al' theme
local others_pattern = "[;,]? *%f[%a]and [Oo]thers"; -- and alternate to et al.
if name:match (etal_pattern) then -- variants on et al.
name = name:gsub (etal_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
add_maint_cat ('etal'); -- and add a category if not already added
end
elseif name:match (others_pattern) then -- if not 'et al.', then 'and others'?
name = name:gsub (others_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
add_maint_cat ('etal'); -- and add a category if not already added
end
end
end
return name, etal; --
end
--[[--------------------------< E X T R A C T _ N A M E S >----------------------------------------------------
Gets name list from the input arguments
Searches through args in sequential order to find |lastn= and |firstn= parameters (or their aliases), and their matching link and mask parameters.
Stops searching when both |lastn= and |firstn= are not found in args after two sequential attempts: found |last1=, |last2=, and |last3= but doesn't
find |last4= and |last5= then the search is done.
This function emits an error message when there is a |firstn= without a matching |lastn=. When there are 'holes' in the list of last names, |last1= and |last3=
are present but |last2= is missing, an error message is emitted. |lastn= is not required to have a matching |firstn=.
When an author or editor parameter contains some form of 'et al.', the 'et al.' is stripped from the parameter and a flag (etal) returned
that will cause list_people() to add the static 'et al.' text from Module:Citation/CS1/Configuration. This keeps 'et al.' out of the
template's metadata. When this occurs, the page is added to a maintenance category.
]]
local function extract_names(args, list_name)
local names = {}; -- table of names
local last; -- individual name components
local first;
local link;
local mask;
local i = 1; -- loop counter/indexer
local n = 1; -- output table indexer
local count = 0; -- used to count the number of times we haven't found a |last= (or alias for authors, |editor-last or alias for editors)
local etal=false; -- return value set to true when we find some form of et al. in an author parameter
local err_msg_list_name = list_name:match ("(%w+)List") .. 's list'; -- modify AuthorList or EditorList for use in error messages if necessary
while true do
last = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1
first = select_one( args, cfg.aliases[list_name .. '-First'], 'redundant_parameters', i );
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i );
mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i );
last, etal = name_has_etal (last, etal, false); -- find and remove variations on et al.
first, etal = name_has_etal (first, etal, false); -- find and remove variations on et al.
if first and not last then -- if there is a firstn without a matching lastn
append_error( 'first_missing_last', {err_msg_list_name, i}); -- add this error message
elseif not first and not last then -- if both firstn and lastn aren't found, are we done?
count = count + 1; -- number of times we haven't found last and first
if 2 <= count then -- two missing names and we give up
break; -- normal exit or there is a two-name hole in the list; can't tell which
end
else -- we have last with or without a first
names[n] = {
last = last,
first = first,
link = link,
mask = mask,
origin = list_name:match ("(%w+)List"):lower() .. '-link' .. i,
corporate=false
}; -- add this name to our names list (corporate for |vauthors= only)
n = n + 1; -- point to next location in the names table
if 1 == count then -- if the previous name was missing
append_error( 'missing_name', {err_msg_list_name, i-1}); -- add this error message
end
count = 0; -- reset the counter, we're looking for two consecutive missing names
end
i = i + 1; -- point to next args location
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >--------------------------------
This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and
|xxxxor-linkn= in args. It then returns a table of assembled names just as extract_names() does.
Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
tests, are wrapped in doubled paranethese ((corporate name)) to suppress the format tests.
This function sets the vancouver error when a reqired comma is missing and when there is a space between an author's initials.
]]
local function parse_vauthors_veditors (args, vparam, list_name)
local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn=
local v_name_table = {};
local etal = false; -- return value set to true when we find some form of et al. vauthors parameter
local last, first, link, mask;
local corporate = false;
vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period)
if vparam:find ('%[%[') or vparam:find ('%]%]') then -- no wikilinking vauthors names
add_vanc_error ();
end
v_name_table = mw.text.split(vparam, "%s*,%s*") -- names are separated by commas
for i, v_name in ipairs(v_name_table) do
if v_name:match ('^%(%(.+%)%)$') then -- corporate authors are wrapped in doubled parenthese to supress vanc formatting and error detection
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
last = v_name:match ('^%(%((.+)%)%)$')
corporate = true;
elseif string.find(v_name, "%s") then
lastfirstTable = {}
lastfirstTable = mw.text.split(v_name, "%s")
first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be author intials
last = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials
if mw.ustring.match (last, '%a+%s+%u+%s+%a+') or mw.ustring.match (v_name, ' %u %u$') then
add_vanc_error (); -- matches last II last; the case when a comma is missing or a space between two intiials
end
else
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
last = v_name; -- last name or single corporate name? Doesn't support multiword corporate names? do we need this?
end
if is_set (first) and not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else
add_vanc_error ();
end
-- this from extract_names ()
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i );
mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i );
names[i] = {last = last, first = first, link = link, mask = mask, corporate=corporate}; -- add this assembled name to our names list
end
return names, etal; -- all done, return our list of names
end
--[[--------------------------< S E L E C T _ A U T H O R S _ E D I T O R S _ F R O M _ S O U R C E >------------------
Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or
select one of |editors=, |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list.
Only one of these appropriate three will be used. The hierarchy is: |authorn= (and aliases) highest and |authors= lowest and
similarly, |editorn= (and aliases) highest and |editors= lowest
When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second
test which mimicks the test used in extract_names() when looking for a hole in the author name list. There may be a better
way to do this, I just haven't discovered what that way is.
Emits an error message when more than one xxxxor name source is provided.
In this function, vxxxxors = vauthors or veditors; xxxxors = authors or editors as appropriate.
]]
local function select_authors_editors_from_source (vxxxxors, xxxxors, args, list_name, vparam, name_list_format)
local lastfirst = false;
if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a first 1 without a last1
select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 2 ) then
lastfirst = true;
end
if ( is_set ( vxxxxors ) and true == lastfirst ) or -- these are the three error conditions
( is_set ( vxxxxors ) and is_set ( xxxxors ) ) or
( lastfirst and is_set ( xxxxors ) ) then
local err_name;
if 'AuthorList' == list_name then -- figure out which name should be used in error message
err_name = 'author';
else
err_name = 'editor';
end
append_error( 'redundant_parameters', {err_name .. '-name-list parameters'});
-- add error message
end
local x, xxxxor_etal;
if not lastfirst then
if is_set ( vxxxxors ) then
x, xxxxor_etal = parse_vauthors_veditors ( args, vparam, list_name );
-- fetch author list from |vxxxxor=, |xxxxor-linkn=, and |xxxxor-maskn=
return x, xxxxor_etal, nil , 'vanc';
elseif is_set ( xxxxors ) then
return {}, nil, xxxxors, name_list_format; -- use content of |xxxxor=
end
end;
x, xxxxor_etal = extract_names ( args, list_name ); -- fetch xxxxor list from |xxxxorn= / |lastn= / |firstn=, |xxxxor-linkn=, and |xxxxor-maskn=, or
return x, xxxxor_etal, nil, name_list_format; -- no xxxxors at all; this allows missing xxxxor name test to run in case there is a first without last
end
local function get_people (handle, para, args, page_name)
local author_etal;
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors=
local Authors;
local NameListFormat = para.namelistformat;
a, author_etal, Authors, NameListFormat = select_authors_editors_from_source(
handle.vauthors,
handle.authors,
args,
'AuthorList',
args.vauthors,
NameListFormat
);
local Coauthors = handle.coauthors;
local editor_etal;
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors=
local Editors;
e, editor_etal, Editors, NameListFormat = select_authors_editors_from_source(
handle.veditors,
handle.editors,
args,
'EditorList',
args.veditors,
NameListFormat
);
local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs
local Translators; -- assembled translators name list
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs
local Contributors; -- assembled contributors name list
local Contribution = handle.contribution;
if para.contributorsvalid then
c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn=
if 0 < #c then
if not is_set (Contribution) then -- |contributor= requires |contribution=
append_error( 'contributor_missing_required_param', {'contribution'});
-- add missing contribution error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
if 0 == #a then -- |contributor= requires |author=
append_error( 'contributor_missing_required_param', {'author'});-- add missing author error message
c = {}; -- blank the contributors' table; it is used as a flag later
end
end
else -- if not a book cite
if select_one (args, cfg.aliases['ContributorList-Last'], 'redundant_parameters', 1 ) then -- are there contributor name list parameters?
append_error( 'contributor_ignored', {}); -- add contributor ignored error message
end
Contribution = nil; -- unset
end
local LastAuthorAmp = para.lastauthoramp;
if (in_array (NameListFormat, {'&', 'amp'})) then
LastAuthorAmp = 'yes'; -- override |lastauthoramp = if |name-list-format = is set to '&' or 'amp'
end
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list
do
local last_first_list;
local maximum;
local control = {
format = NameListFormat, -- empty string, 'vanc', or 'amp'
maximum = nil, -- as if display-authors or display-editors not set
lastauthoramp = LastAuthorAmp,
page_name = page_name -- get current page name so that we don't wikilink to it via editorlinkn
};
do -- do editor name list first because coauthors can modify control table
maximum , editor_etal = get_display_authors_editors (para.displayeditors, #e, 'editors', editor_etal);
--[[ Preserve old-style implicit et al.
临时修复"Category:含有旧式缩略标签的引用的页面 in editors"的问题,中文版目前与英文版逻辑不一样,暂时不需要这个分类。等以后更新时再看怎么处理 --2017.6.23 shizhao
if not is_set(maximum) and #e == 4 then
maximum = 3;
append_error('implict_etal_editor', {});
end
]]
control.maximum = maximum;
last_first_list, EditorCount = list_people(control, e, editor_etal, 'editor');
if is_set (Editors) then
if editor_etal then
Editors = Editors .. ' ' .. cfg.messages['et al']; -- add et al. to editors parameter beause |display-editors=etal
EditorCount = 2; -- with et al., |editors= is multiple names; spoof to display (eds.) annotation
else
EditorCount = 2; -- we don't know but assume |editors= is multiple names; spoof to display (eds.) annotation
end
else
Editors = last_first_list; -- either an author name list or an empty string
end
if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then
EditorCount = 2; -- spoof to display (eds.) annotation
end
end
do -- now do translators
control.maximum = #t; -- number of translators
Translators = list_people(control, t, false, 'translator'); -- et al not currently supported
end
do -- now do contributors
control.maximum = #c; -- number of contributors
Contributors = list_people(control, c, false, 'contributor'); -- et al not currently supported
end
do -- now do authors
control.maximum , author_etal = get_display_authors_editors (para.displayauthors, #a, 'authors', author_etal);
if is_set(Coauthors) then -- if the coauthor field is also used, prevent ampersand and et al. formatting.
para.lastauthoramp = nil;
control.maximum = #a + 1;
end
last_first_list = list_people(control, a, author_etal, 'author');
if is_set (Authors) then
Authors, author_etal = name_has_etal (Authors, author_etal, false); -- find and remove variations on et al.
if author_etal then
Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter
end
else
Authors = last_first_list; -- either an author name list or an empty string
end
end -- end of do
if is_set(Authors) then
if is_set(Coauthors) then
if 'vanc' == NameListFormat then -- separate authors and coauthors with proper name-list-separator
Authors = Authors .. ', ' .. Coauthors;
else
Authors = Authors .. '; ' .. Coauthors;
end
end
elseif is_set(Coauthors) then -- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specified
append_error('coauthors_missing_author', {}); -- emit error message
end
end
local multiple_editors = EditorCount >1;
local has_contributors = false;
local NameList = {}; -- holds selected contributor, author, editor name list
if #c > 0 then -- if there is a contributor list
NameList = c; -- select it
has_contributor = true;
elseif #a > 0 then -- or an author list
NameList = a;
elseif #e > 0 then -- or an editor list
NameList = e;
end
return Authors, Contributors, Editors, Translators, Contribution, NameList, multiple_editors, has_contributors;
end
--[[--------------------------< T E R M I N A T E _ N A M E _ L I S T >----------------------------------------
This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space
when the last character is not a sepc character or when the last three characters are not sepc followed by two
closing square brackets (close of a wikilink). When either of these is true, the name_list is terminated with a
single space character.
]]
local function terminate_name_list (name_list, sepc)
if (string.sub (name_list,-1,-1) == sepc) or (string.sub (name_list,-3,-1) == sepc .. ']]') then -- if last name in list ends with sepc char
return name_list .. " "; -- don't add another
else
return name_list .. sepc .. ' '; -- otherwise terninate the name list
end
end
--[[--------------------------< F O R M A T _ P E O P L E >------------------------------------------------
]]
local function format_people (Authors, Editors, Contributors, multiple_editors, use_in, sepc)
if is_set (Authors) then
Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space
if is_set (Editors) then
local in_text = " ";
local post_text = "";
if use_in then
in_text = in_text .. " " .. cfg.messages['in'];
if (sepc ~= '.') then in_text = in_text:lower() end -- lowercase for cs2
else
if multiple_editors then
post_text = ", " .. cfg.messages['editors'];
else
post_text = ", " .. cfg.messages['editor'];
end
end
Editors = terminate_name_list (Editors .. in_text .. post_text, sepc);
-- terminate with 0 or 1 sepc and a space
end
if is_set (Contributors) then -- book cite and we're citing the intro, preface, etc
local by_text = sepc .. ' ' .. cfg.messages['by'] .. ' ';
if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2
Authors = by_text .. Authors; -- author follows title so tweak it here
if is_set (Editors) then -- when Editors make sure that Authors gets terminated
Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space
end
Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space
end
else
if is_set (Editors) then
if multiple_editors then
Editors = Editors .. " (" .. cfg.messages['editors'] .. ")" .. sepc .. " "
else
Editors = Editors .. " (" .. cfg.messages['editor'] .. ")" .. sepc .. " "
end
end
end
return Authors, Editors, Contributors;
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, error_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set;
in_array = utilities_page_ptr.in_array;
add_maint_cat = error_page_ptr.add_maint_cat;
append_error = error_page_ptr.append_error;
select_one = error_page_ptr.select_one;
make_internal_link = links_page_ptr.make_internal_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
get_people = get_people,
format_people = format_people,
set_selected_modules = set_selected_modules
}
34b4459f64df67c8563c0ec14c8ddfbba8196c57
Module:Citation/CS1/COinS
828
205
429
428
2024-08-04T12:22:23Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]
local is_set, in_array, remove_wiki_link, strip_apostrophe_markup; -- functions in Module:Citation/CS1/Utilities and Module:Citation/CS1/Links
local cfg; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration
--[[--------------------------< M A K E _ C O I N S _ T I T L E >----------------------------------------------
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn't corrupted with strings
of %27%27...
]]
local function make_coins_title (title, script)
if is_set (title) then
title = strip_apostrophe_markup (title); -- strip any apostrophe markup
else
title = ''; -- if not set, make sure title is an empty string
end
if is_set (script) then
script = script:gsub ('^%l%l%s*:%s*', ''); -- remove language prefix if present (script value may now be empty string)
script = strip_apostrophe_markup (script); -- strip any apostrophe markup
else
script = ''; -- if not set, make sure script is an empty string
end
if is_set (title) and is_set (script) then
script = ' ' .. script; -- add a space before we concatenate
end
return title .. script; -- return the concatenation
end
--[[--------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------
Returns a string where all of Lua's magic characters have been escaped. This is important because functions like
string.gsub() treat their pattern and replace strings as patterns, not literal strings.
]]
local function escape_lua_magic_chars (argument)
argument = argument:gsub("%%", "%%%%"); -- replace % with %%
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other Lua magic pattern characters
return argument;
end
--[[--------------------------< G E T _ C O I N S _ P A G E S >------------------------------------------------
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.
]]
local function get_coins_pages (pages)
local pattern;
if not is_set (pages) then return pages; end -- if no page numbers then we're done
while true do
pattern = pages:match("%[(%w*:?//[^ ]+%s+)[%w%d].*%]"); -- pattern is the opening bracket, the URL and following space(s): "[url "
if nil == pattern then break; end -- no more URLs
pattern = escape_lua_magic_chars (pattern); -- pattern is not a literal string; escape Lua's magic pattern characters
pages = pages:gsub(pattern, ""); -- remove as many instances of pattern as possible
end
pages = pages:gsub("[%[%]]", ""); -- remove the brackets
pages = pages:gsub("–", "-" ); -- replace endashes with hyphens
pages = pages:gsub("&%w+;", "-" ); -- and replace HTML entities (– etc.) with hyphens; do we need to replace numerical entities like   and the like?
return pages;
end
--[=[-------------------------< C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R >------------------
There are three options for math markup rendering that depend on the editor's math preference settings. These
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are
PNG images
TeX source
MathML with SVG or PNG fallback
All three are heavy with HTML and CSS which doesn't belong in the metadata.
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings
of the last editor to save the page.
This function gets the rendered form of an equation according to the editor's preference before the page is saved. It
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial
value. To replace multipe equations it is necessary to call this function from within a loop.
]=]
local function coins_replace_math_stripmarker (value)
local stripmarker = cfg.stripmarkers['math'];
local rendering = value:match (stripmarker); -- is there a math stripmarker
if not rendering then -- when value doesn't have a math stripmarker, abandon this test
return false, value;
end
rendering = mw.text.unstripNoWiki (rendering); -- convert stripmarker into rendered value (or nil? ''? when math render error)
if rendering:match ('alt="[^"]+"') then -- if PNG math option
rendering = rendering:match ('alt="([^"]+)"'); -- extract just the math text
elseif rendering:match ('$%s+.+%s+%$') then -- if TeX math option; $ is legit character that is escapes as \$
rendering = rendering:match ('$%s+(.+)%s+%$') -- extract just the math text
elseif rendering:match ('<annotation[^>]+>.+</annotation>') then -- if MathML math option
rendering = rendering:match ('<annotation[^>]+>(.+)</annotation>') -- extract just the math text
else
return false, value; -- had math stripmarker but not one of the three defined forms
end
return true, value:gsub (stripmarker, rendering, 1);
end
--[[--------------------------< C O I N S _ C L E A N U P >----------------------------------------------------
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities.
2015-12-10: there is a bug in mw.text.unstripNoWiki (). It replaces math stripmarkers with the appropriate content
when it shouldn't. See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible
characters table?
]]
local function coins_cleanup (value)
local replaced = true; -- default state to get the do loop running
while replaced do -- loop until all math stripmarkers replaced
replaced, value = coins_replace_math_stripmarker (value); -- replace math stripmarker with text representation of the equation
end
value = value:gsub (cfg.stripmarkers['math'], "MATH RENDER ERROR"); -- one or more couldn't be replaced; insert vague error message
value = mw.text.unstripNoWiki (value); -- replace nowiki stripmarkers with their content
value = value:gsub ('<span class="nowrap" style="padding%-left:0%.1em;">'(s?)</span>', "'%1"); -- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s
value = value:gsub (' ', ' '); -- replace entity with plain space
value = value:gsub ('\226\128\138', ' '); -- replace hair space with plain space
if not mw.ustring.find (value, cfg.indic_script) then -- don't remove zero-width joiner characters from indic script
value = value:gsub ('‍', ''); -- remove ‍ entities
value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', ''); -- remove zero-width joiner, zero-width space, soft hyphen
end
value = value:gsub ('[\009\010\013 ]+', ' '); -- replace horizontal tab, line feed, carriage return with plain space
return value;
end
--[[--------------------------< C O I N S >--------------------------------------------------------------------
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.
]]
local function COinS (data, class)
if 'table' ~= type (data) or nil == next (data) then
return '';
end
for k, v in pairs (data) do -- spin through all of the metadata parameter values
if 'ID_list' ~= k and 'Authors' ~= k then -- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)
data[k] = coins_cleanup (v);
end
end
local ctx_ver = "Z39.88-2004";
-- treat table strictly as an array with only set values.
local OCinSoutput = setmetatable ({}, {
__newindex = function(self, key, value)
if is_set (value) then
rawset (self, #self+1, table.concat {key, '=', mw.uri.encode (remove_wiki_link (value))});
end
end
});
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn', 'journal', 'news', 'magazine'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or
('citation' == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"; -- journal metadata identifier
if in_array (class, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) then -- set genre according to the type of citation template we are rendering
OCinSoutput["rft.genre"] = "preprint"; -- cite arxiv, cite biorxiv, cite citeseerx, cite ssrn
elseif 'conference' == class then
OCinSoutput["rft.genre"] = "conference"; -- cite conference (when Periodical set)
elseif 'web' == class then
OCinSoutput["rft.genre"] = "unknown"; -- cite web (when Periodical set)
else
OCinSoutput["rft.genre"] = "article"; -- journal and other 'periodical' articles
end
OCinSoutput["rft.jtitle"] = data.Periodical; -- journal only
if is_set (data.Map) then
OCinSoutput["rft.atitle"] = data.Map; -- for a map in a periodical
else
OCinSoutput["rft.atitle"] = make_coins_title (data.Title, data.ScriptTitle);
-- all other 'periodical' article titles
end
-- these used onlu for periodicals
OCinSoutput["rft.ssn"] = data.Season; -- keywords: winter, spring, summer, fall
OCinSoutput["rft.chron"] = data.Chron; -- free-form date components
OCinSoutput["rft.volume"] = data.Volume; -- does not apply to books
OCinSoutput["rft.issue"] = data.Issue;
OCinSoutput["rft.pages"] = get_coins_pages (data.Pages); -- also used in book metadata
elseif 'thesis' ~= class then -- all others except cite thesis are treated as 'book' metadata; genre distinguishes
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"; -- book metadata identifier
if 'report' == class or 'techreport' == class then -- cite report and cite techreport
OCinSoutput["rft.genre"] = "report";
elseif 'conference' == class then -- cite conference when Periodical not set
OCinSoutput["rft.genre"] = "conference";
elseif in_array (class, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) then
if is_set (data.Chapter) or is_set (data.ScriptChapter) then
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.atitle"] = make_coins_title (data.Chapter, data.ScriptChapter);
-- book chapter, encyclopedia article, interview in a book, or map title
else
if 'map' == class or 'interview' == class then
OCinSoutput["rft.genre"] = 'unknown'; -- standalone map or interview
else
OCinSoutput["rft.genre"] = 'book'; -- book and encyclopedia
end
end
else --{'AV media', 'AV media notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}
OCinSoutput["rft.genre"] = "unknown";
end
OCinSoutput["rft.btitle"] = make_coins_title (data.Title, data.ScriptTitle);
-- book only
OCinSoutput["rft.place"] = data.PublicationPlace; -- book only
OCinSoutput["rft.series"] = data.Series; -- book only
OCinSoutput["rft.pages"] = get_coins_pages (data.Pages); -- book, journal
OCinSoutput["rft.edition"] = data.Edition; -- book only
OCinSoutput["rft.pub"] = data.PublisherName; -- book and dissertation
else -- cite thesis
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:dissertation"; -- dissertation metadata identifier
OCinSoutput["rft.title"] = make_coins_title (data.Title, data.ScriptTitle);
-- dissertation (also patent but that is not yet supported)
OCinSoutput["rft.degree"] = data.Degree; -- dissertation only
OCinSoutput['rft.inst'] = data.PublisherName; -- book and dissertation
end
-- and now common parameters (as much as possible)
OCinSoutput["rft.date"] = data.Date; -- book, journal, dissertation
for k, v in pairs (data.ID_list) do -- what to do about these? For now assume that they are common to all?
if k == 'ISBN' then v = v:gsub ("[^-0-9X]", ""); end
local id = cfg.id_handlers[k].COinS;
if string.sub (id or "", 1, 4) == 'info' then -- for ids that are in the info:registry
OCinSoutput["rft_id"] = table.concat {id, "/", v};
elseif string.sub (id or "", 1, 3) == 'rft' then -- for isbn, issn, eissn, etc that have defined COinS keywords
OCinSoutput[id] = v;
elseif id then -- when cfg.id_handlers[k].COinS is not nil
OCinSoutput["rft_id"] = table.concat {cfg.id_handlers[k].prefix, v};-- others; provide a url
end
end
local last, first;
for k, v in ipairs (data.Authors) do
last, first = coins_cleanup (v.last), coins_cleanup (v.first or ''); -- replace any nowiki strip markers, non-printing or invisible characers
if k == 1 then -- for the first author name only
if is_set (last) and is_set (first) then -- set these COinS values if |first= and |last= specify the first author name
OCinSoutput["rft.aulast"] = last; -- book, journal, dissertation
OCinSoutput["rft.aufirst"] = first; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation -- otherwise use this form for the first name
end
else -- for all other authors
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat {last, ", ", first}; -- book, journal, dissertation
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- book, journal, dissertation
end
end
end
OCinSoutput.rft_id = data.URL;
OCinSoutput.rfr_id = table.concat {"info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage};
OCinSoutput = setmetatable (OCinSoutput, nil);
-- sort with version string always first, and combine.
table.sort (OCinSoutput);
table.insert (OCinSoutput, 1, "ctx_ver=" .. ctx_ver); -- such as "Z39.88-2004"
return table.concat (OCinSoutput, "&");
end
--[[--------------------------< S E T _ S E L E C T E D _ M O D U L E S >--------------------------------------
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.
]]
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr, links_page_ptr)
cfg = cfg_table_ptr;
is_set = utilities_page_ptr.is_set; -- import functions from selected Module:Citation/CS1/Utilities module
in_array = utilities_page_ptr.in_array;
strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup;
remove_wiki_link = links_page_ptr.remove_wiki_link;
end
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
return {
COinS = COinS,
set_selected_modules = set_selected_modules,
}
a6a4da2d79b0f571a56787451c79021e7a1b4cf1
Module:Transclusion count/data/R
828
206
431
430
2024-08-04T12:22:24Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
["R"] = 16000,
["R/ref"] = 16000,
["RA"] = 11000,
["RMCategory"] = 7700,
["ROC"] = 25000,
["ROC-1912"] = 2100,
["ROC-TW"] = 8000,
["ROK"] = 3200,
["ROU"] = 2500,
["RUS"] = 11000,
["Rail-interchange"] = 15000,
["Rail-interchange/cn"] = 9000,
["Rail_color"] = 14000,
["Rail_pass_box"] = 3200,
["RankedMedalTable"] = 2100,
["Rcr"] = 13000,
["Rdt_intro"] = 3100,
["Re"] = 2200,
["Red"] = 3300,
["Redirect"] = 2800,
["Redirect_category_shell"] = 156000,
["Redirect_template"] = 508000,
["Redirect_template/st"] = 376000,
["Ref"] = 2300,
["Ref_label"] = 3700,
["Refbegin"] = 61000,
["Refend"] = 61000,
["Refimprove"] = 33000,
["Reflist"] = 982000,
["ReflistF"] = 64000,
["ReflistH"] = 65000,
["ReflistH/styles.css"] = 65000,
["Refnest"] = 4300,
["Refs"] = 2800,
["RegioneIT"] = 6000,
["RegioneIT_(coat_of_arms)"] = 6000,
["Registration_required"] = 17000,
["Remark"] = 7900,
["Remind"] = 3300,
["Remove_first_word"] = 34000,
["Replace"] = 15000,
["Reply"] = 21000,
["Reply_to"] = 21000,
["Resize"] = 26000,
["Rint"] = 14000,
["Rmr"] = 2600,
["Rnd"] = 128000,
["Rnd/-"] = 116000,
["Romania-geo-stub"] = 3100,
["Rotten-tomatoes"] = 4400,
["Rotten_Tomatoes"] = 6300,
["Rough_translation"] = 6000,
["Roughtranslation"] = 2500,
["Rounddown"] = 4800,
["Routemap"] = 9200,
["Routemap/styles.css"] = 11000,
["RoutemapRoute"] = 4200,
["Rp"] = 14000,
["Ru_icon"] = 3200,
["Ruby"] = 2400,
["Ruby/styles.css"] = 2500,
["Russia-geo-stub"] = 5100,
["Russia-stub"] = 2700,
["Module:Redirect"] = 64000,
["Module:Redirect_category_shell"] = 156000,
["Module:Redirect_hatnote"] = 3000,
["Module:Redirect_template"] = 508000,
["Module:Reply_to"] = 26000,
["Module:ResolveEntityId"] = 120000,
["Module:Road_data/extra"] = 2400,
["Module:Road_data/parser"] = 2700,
["Module:Roman"] = 31000,
["Module:RouteSequence"] = 14000,
["Module:Routemap"] = 11000,
}
57fa4d820f05479ac73afddd42b7638f09e3a09a
Template:Oldid
10
207
433
432
2024-08-04T12:22:24Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span class="plainlinks">{{#if:{{{page|{{{1|}}}}}}
|[{{fullurl:{{{page|{{{1}}}}}}|oldid={{{oldid|{{{2|}}}}}} {{{label|{{{4|'''{{{page|{{{1}}}}}}'''的{{{3|{{#if:{{{oldid|{{{2|}}}}}}
|版本{{{oldid|{{{2}}}}}}
|當前版本}}
}}}}}}}}}
}}]
|[[Special:固定链接/{{trim|{{{oldid|{{{2|}}}}}}}}|{{#if:{{{oldid|{{{2|}}}}}}
|{{{label|{{{4|{{{3|歷史版本{{{oldid|{{{2}}}}}}}}}}}}}}}
|{{{label|{{{4|{{{3|Special:固定链接}}}}}}}}}
}}]]
}}</span><noinclude>
{{template doc}}
</noinclude>
1812a13200996d26821a9347bca0c78709670826
Template:Templatedataheader
10
208
435
434
2024-08-04T12:22:24Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:TemplateData header]]
ed82fd29d375c3f39a93c690ac9d02cf1cebcb04
Template:Reflist/doc
10
209
437
436
2024-08-04T12:22:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{Documentation subpage}}
{{High-use|all-pages=yes}}
{{Esoteric}}
<!-- 在本行下編輯模板說明 -->
使用本模板可在條目中顯示註腳({{tag|ref}})列表。其涵盖了{{tag|references|s}}的所有功能。
==参数解说 ==
{{tlc|1=Reflist|2=欄位數/欄位寬度|3=group=组别|4=refs=列表內容|5=liststyle=|6=list=}}
本模板所有参数均为可选
; 无名参数1
: 按固定寬度分欄(填入[[em (字体排印学)|em]]等排印单位):如{{tlc|Reflist|25em}},瀏覽器會依照這個數值和當前的視窗大小,自動調整欄位數目。
: 按列数分欄(填入自然数;此機制不建議使用):如{{tlc|Reflist|2}}將會創造出一個兩欄式的的注釋列表,而{{tlc|Reflist|3}}會產生一個三欄式的列表。視窗大小可变,请慎重定义列数。
: 不填任何内容默认为1。
; <code>group</code>
: 参见[[#分組註釋|分组注释]]
; <code>refs</code>
: 将脚注内容集中到一起存放,参见[[#统一存放参考信息集]]
; <code>liststyle</code>
:
; <code>list</code>
: 手工列出一般参考资料,使用此参数时,模板原本列出{{tag|references|s}}的功能会无效化。可用{{tl|ReflistH}}/{{tl|ReflistF}}模板替代。
=== 过时参数 ===
; <code>colwidth</code>
: 已合并到无名参数1
== 用法 ==
{{markup|title=只使用内文注释
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist}}
}}
{{markup|title=只使用一般注释
|<nowiki>一條青龍一氣通,二盤連莊二本場。
==參考資料==
{{Reflist|list=
* 书目a
* 书目b
}}</nowiki>
|一條青龍一氣通,二盤連莊二本場。
{{fake heading|參考資料}}
{{Reflist|list=
* 书目a
* 书目b
}}
}}
{{markup|title=内文与一般注释混合使用
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist}}
{{Reflist|list=
* 书目a
* 书目b
}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist}}
{{Reflist|list=
* 书目a
* 书目b
}}
}}
=== 分栏 ===
{{Rellink|不支持Internet Explorer 9、Firefox 1.0、Safari 2、Opera 11.0及更低版本,这些浏览器只会显示为单行}}
複數欄位是使用 [[CSS|CSS3]] 作為基礎,目前使用[[Gecko]](如[[Mozilla Firefox]]等)与[[Kestrel]]([[Opera (瀏覽器)]]9.5及以上版本)作排版引擎的瀏覽器會得到較佳的效果{{efn-ur|1={{cite web|url=http://www.stuffandnonsense.co.uk/archives/css3_multi-column_thriller.html|title=CSS3 Multi-Column Thriller|accessdate=2006年11月24日|date=2005年12月30日}}}},但由於 CSS 是網頁上的標準之一,因此日後將能適用在更多的瀏覽器{{efn-ur|1={{cite web|url=http://www.w3.org/TR/css3-multicol|title=CSS3 module: Multi-column layout|publisher=[[World Wide Web Consortium|W3C]]|date=2005年12月15日|accessdate=2006年11月24日}}}}。
按宽度分栏(例如<code><nowiki>{{Reflist|30em}}</nowiki></code>)会让浏览器在给定最小宽度的前提下(如宽度至少为30 em),显示尽可能多的栏目。宽度单位支持em, ex, in, cm, mm, pt, pc, px,但是通常使用em。数字和单位之间不能有空格。不支持使用百分比。
根据参考内容的宽度选择合适的宽度:
* 30em:当有大量参考文献且参考条目有一页宽时适用。例如:{{oldid|張伯苓|71040939#参考文献}}
* 20em:当有宽度较短的[[哈佛参考文献格式]](如{{t1|Template:Sfn}})时适用。例如:{{oldid|南方十字 (无字小说)|71611463#脚注}}.
{{markup|title=分为2栏
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist|2}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist|2}}
}}
{{markup|title=按30em宽度分栏
|<nowiki>一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
==參考資料==
{{Reflist|30em}}</nowiki>
|一條青龍一氣通<ref>參考1</ref>,二盤連莊二本場<ref>參考2</ref>。
{{fake heading|參考資料}}
{{Reflist|30em}}
}}
=== 分組註釋 ===
於2008年6月開始,腳註系統支援了把註釋分成不同組合。這允許組合註釋、參考以及其他。請參閱 {{en icon}}[[:en:Wikipedia:Footnotes#Separating reference lists and explanatory notes|Wikipedia:Footnotes#Separating reference lists and explanatory notes]]。
標籤的原始碼为{{tag|ref group=''"groupname"''|open}},对应註腳列表的原始碼,{{tlx|Reflist|group=''"groupname"''}}。而其中的「groupname」是組合的名稱,如「注」、「参」或「标签」。注意groupname对简繁体敏感。
部分分组会显示特殊效果,如{{tag|ref|params=group="upper-alpha"}}的生成的脚注为{{dummy ref|A}},{{tag|ref|params=group="lower-alpha"}}生成的为{{dummy ref|a}}。
{{markup | title = 按“注释”和“参考”分组
|<nowiki>三元兼四喜,滿貫<ref group="注释">注释1</ref>遇全么<ref group="参考">参考1</ref>。
花<ref group="注释">注释2</ref>自槓頭髮,月從海底撈<ref group="参考">参考2</ref>。
==注释和参考资料==
===注释===
{{Reflist|group=注释}}
===参考===
{{Reflist|group=参考}}</nowiki>
|三元兼四喜,滿貫<ref group="注释">注释1</ref>遇全么<ref group="参考">参考1</ref>。
花<ref group="注释">注释2</ref>自槓頭髮,月從海底撈<ref group="参考">参考2</ref>。
{{fake heading|注释和参考资料}}
{{fake heading|sub=3|注释}}
{{Reflist|group=注释}}
{{fake heading|sub=3|参考}}
{{Reflist|group=参考}}
}}
=== 统一存放参考信息集 ===
<!-- As of September 2009, references may be defined within {{tl|Reflist}} using {{para|refs}} and invoked within the content. There are new error messages associated with this update, documented at [[Help:Cite errors]]. -->
从2014年2月开始,该模板可以通过{{para|refs}}统一存放注脚信息来方便管理。此次更新的相關引用错误问题的提示文件見[[:en:Help:Cite errors]]。
{{markup | title = 示例
|<nowiki>这是参考A<ref name="refname1" />。
这是参考B<ref name="refname2" />。
==参考资料==
{{Reflist|refs=
<ref name="refname1">内容1</ref>
<ref name="refname2">内容2</ref>
}}</nowiki>
|这是参考A<ref name="refname1" group=upper-alpha/>。
这是参考B<ref name="refname2" group=upper-alpha/>。
{{fake heading|参考资料}}
{{Reflist|group=upper-alpha|refs=
<ref name="refname1">内容1</ref>
<ref name="refname2">内容2</ref>
}}
}}
==模板數據==
{{templatedataheader}}
<templatedata>
{
"description": "在條目中加入一個使用較小字級顯示的註腳列表。",
"params": {
"colwidth": {
"label": "欄位的寬度",
"description": "瀏覽器會依照這個數值和當前的視窗大小自動調整欄位數目,請依照該頁面中注釋的平均寬度來填寫欄位的寬度數值。填入後參數「1」將被忽略。",
"type": "string/line",
"required": false
},
"1": {
"label": "欄位的數目",
"description": "欄位的數目,填入2將創造一個兩欄式的的注釋列表,如此類推。",
"type": "number",
"default": "1",
"required": false
},
"list": {
"label": "自定義註釋內容",
"description": "自定義註釋內容。",
"default": "<references />",
"type": "string",
"required": false
},
"refs": {
"type": "string",
"required": false
},
"group": {
"label": "註腳組別名稱",
"description": "註腳組別的名稱,即在插入參考文獻時「使用此組」輸入的名稱。",
"type": "string/line",
"required": false
}
}
}
</templatedata>
==参考文献==
{{notelist-ur}}
==參見==
* {{tlx|ReferencesWithExtra}}
* {{tlx|Notelist}}
* {{tlx|Template reference list}}
* 在討論頁顯示參考文獻請用{{tlx|Reflist-talk}}
* [[Help:脚注]]
* [[Wikipedia:列明来源]]
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[Wikipedia:Wikidata]]) -->
[[Category:引用模板| ]]
[[Category:頁面訊息模板|註]]
}}</includeonly>
== 重定向 ==
* {{模板鏈接|註腳}}
ae69ecb71e6788aa15a356de1ed3c91e6f058be2
Template:模板鏈接
10
210
439
438
2024-08-04T12:22:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Tl]]
69fe34340c46c356e0b01b31ca783b9a5e2a388d
Template:Infobox Douyin personality
10
211
441
440
2024-08-04T12:23:53Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Infobox
| child = {{Yesno|{{{embed|no}}}}}
| bodyclass = biography vcard
| title = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes|<div align=center style="background-color:#411445; color:#FFF;">'''抖-{}-音资料'''</div>}}
| abovestyle = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||background-color: #411445; color: white}}
| above = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{br separated entries
|1={{#if:{{{honorific prefix|{{{honorific_prefix|}}}}}}|<span class="honorific-prefix" style="font-size: small">{{{honorific prefix|{{{honorific_prefix|}}}}}}</span>}}
|2={{#if:{{{name|<includeonly>{{PAGENAMEBASE}}</includeonly>}}}|<span class="fn">{{{name|{{PAGENAMEBASE}}}}}</span>}}
|3={{#if:{{{honorific suffix|{{{honorific_suffix|}}}}}}|<span class="honorific-suffix" style="font-size: small">{{{honorific suffix|{{{honorific_suffix|}}}}}}</span>}}
}}
}}
| image = {{#invoke:InfoboxImage|InfoboxImage|image={{{logo|}}}|size={{{logo_size|}}}|sizedefault=250px|alt={{{logo_alt|}}}}}
| caption = {{{logo caption|}}}
| image2 = {{#invoke:InfoboxImage|InfoboxImage|image={{{image|}}}|size={{{image size|{{{image_size|{{{imagesize|}}}}}}}}}|sizedefault=frameless|upright=1|alt={{{alt|}}}|suppressplaceholder=yes}}
| caption2 = {{{image caption|{{{caption|{{{image_caption|}}}}}}}}}
| headerstyle = background-color: {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes|{{{header-color|transparent}}}|#411445; color: white}}; line-height: 1.5em
| labelstyle = white-space: nowrap;
| header1 = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{#if:{{{birth_name|}}}{{{birth_date|}}}{{{birth_place|}}}{{{death_date|}}}{{{death_place|}}}{{{height|}}}{{{nationality|}}}{{{residence|}}}{{{occupation|}}}|个人资料}}}}
| label3 = 出生
| data3 = {{br separated entries|1={{#if:{{{birth_name|}}}|<span style="white-space:normal;">{{{birth_name|}}}</span>}}|2={{{birth_date|}}}|3={{#if:{{{birth_place|}}}|<span class="birthplace">{{{birth_place|}}}</span>}}}}
| label4 = 逝世
| data4 = {{br separated entries|1={{{death_date|}}}|2={{#if:{{{death_place|}}}|<span class="deathplace">{{{death_place|}}}</span>}}}}
| label5 = 出道地點
| data5 = {{{Origin|{{{origin|}}}}}}
| label6 = 國籍
| data6 = {{{nationality|}}}
| class6 = category
| label7 = 教育程度
| data7 = {{{education|}}}
| label8 = 居住地
| data8 = {{{residence|}}}
| class8 = {{#if:{{{death_date|}}}{{{death_place|}}}||label}}
| label9 = 職業
| data9 = {{{occupation|}}}
| class9 = role
| label10 = 身高
| data10 = {{#if:{{{height_m|{{{height_cm|}}}}}}{{{height_ft|}}}{{{height_in|}}} | {{convinfobox|{{{height_m|{{{height_cm|}}}}}}|{{#if:{{{height_m|}}}|m|cm}}|{{{height_ft|}}}|ft|{{{height_in|}}}|in}} }}{{#if:{{{height|}}} | {{Infobox person/height|{{{height|}}}}} }}
| label11 = 宗教信仰
| data11 = {{{religion|}}}
| class11 = category
| label12 = 伴侶
| data12 = {{{partner|}}}
| label13 = 配偶
| data13 = {{{spouse|}}}
| label14 = 簽名
| data14 = {{#if:{{{signature|}}}|{{#invoke:InfoboxImage|InfoboxImage|image={{{signature|}}}|size={{{signature_size|}}}|sizedefault=150px|alt={{{signature alt|{{{signature_alt|}}}}}}}} }}
| label15 = 網站
| data15 = {{{website|{{{homepage|{{{URL|}}}}}}}}}
| header20 = {{#ifeq:{{Yesno|{{{embed|no}}}}}|yes||{{#if:{{{pseudonym|}}}{{{channel_name|}}}{{{channel_url|}}}{{{channel_direct_url|}}}{{{years active|{{{years_active|{{{yearsactive|}}}}}}}}}{{{genre|}}}{{{subscribers|}}}{{{views|}}}{{{network|}}}{{{associated_acts|}}}{{{catchphrase(s)|}}}|抖音-{}-资料}}}}
| label21 = 網名
| data21 = {{{pseudonym|}}}
| label22 = 頻道
| data22 = {{#if:{{{channel_url|}}}|[{{{channel_url|}}} {{#if:{{{channel_display_name|}}}|{{{channel_display_name|}}}|{{{channels|}}}}}]}}
| label23 = 頻道
| data23 = {{{channels|}}}
| label24 = 頻道
| data24 = {{{channels|}}}
| label25 = 頻道
| data25 = {{{channels|}}}
| label26 = 創辦人
| data26 = {{{creator|}}}
| label27 = 活躍年代
| data27 = {{{years active|{{{years_active|{{{yearsactive|}}}}}}}}}
| label28 = 類型
| data28 = {{{genre|}}}
| label29 = 粉丝数
| data29 = {{br separated entries|1={{{subscribers|}}}|2={{#if:{{{subscriber_date|}}}|(截至{{{subscriber_date|}}})|}}}}
| label30 = 總-{zh-cn:播放数;zh-hk:點擊率;zh-tw:點閱數;}-
| data30 = {{br separated entries|1={{{views|}}}|2={{#if:{{{view_date|}}}|(截至{{{view_date|}}})|}}}}
| label31 = [[多频道网络|網-{zh-cn:络;zh-hk:絡;zh-tw:路;}-]]
| data31 = {{{network|}}}
| label32 = 点赞量
| data32 = {{br separated entries|1={{{Praise quantity|}}}|2={{#if:{{{Praise quantity_date|}}}|(截至{{{Praise quantity_date|}}})|}}}}
| label33 = 相關團體
| data33 = {{{associated_acts|}}}
| label34 = 口頭禪
| data34 = {{{catchphrase(s)|}}}
| belowstyle = color: darkslategray;
| below = {{#if:{{{stats_update|}}}|更新于{{{stats_update}}}|}} {{#if:{{{extra_information|}}}|{{{extra_information}}}}}
}}{{#ifeq:{{{nocat|false}}}|false|}}<noinclude>{{documentation}}</noinclude>
ee4ae4e61a837fd290b590698a43e2e81138239e
Template:Yesno
10
212
443
442
2024-08-04T12:25:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#switch: {{<includeonly>safesubst:</includeonly>lc: {{{1|¬}}} }}
|no
|n
|false
|f
|否
|0 = {{{no|<!-- null -->}}}
| = {{{blank|{{{no|<!-- null -->}}}}}}
|¬ = {{{¬|}}}
|yes
|y
|true
|t
|是
|1 = {{{yes|yes}}}
|#default = {{{def|{{{yes|yes}}}}}}
}}<noinclude>
{{documentation}}
</noinclude>
a0ba60b6ae5ad344f4e4a2ea033770d6131cf7c6
Template:Str left
10
213
445
444
2024-08-04T12:25:18Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{ {{{|safesubst:}}}padleft:|{{{2|1}}}|{{{1}}}}}</includeonly><noinclude>
{{documentation}}
</noinclude>
9c0bdb76d3fd64ecd8af888df4ec235e5aec0b33
Module:InfoboxImage
828
214
447
446
2024-08-04T12:25:21Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- 输入: - 輸入:
-- image - 纯文件名(带有File:/Image:前缀与否皆可)或完全格式化的图片链接 - 純檔案名(帶有File:/Image:字首與否皆可)或完全格式化的圖片連結
-- page - page to display for multipage images (DjVu)
-- size - 显示图像大小 - 顯示影像大小
-- maxsize - 图像最大大小 - 影像最大大小
-- sizedefault - 如果size参数留空,默认显示图像大小 - 如果size參數留空,預設顯示影像大小
-- alt - 图像替换文本 - 影像替換文字
-- title - 图像标题文本 - 影像標題文字
-- border - 有边框则设为yes - 有邊框則設為yes
-- center - 图像需居中则设为yes - 影像需居中則設為yes
-- upright - 垂直图像参数 - 垂直影像參數
-- suppressplaceholder - 设为yes则检查图像是否为占位符并停用 - 設為yes則檢查影像是否為佔位符並停用
-- link - 点击图像时访问的页面 - 點選影像時訪問的頁面
-- 输出: - 輸出:
-- 格式化图像 - 格式化影像
-- 详情请参阅"Module:InfoboxImage/doc"页面 - 詳情請參閱"Module:InfoboxImage/doc"頁面
local i = {};
local placeholder_image = {
"Blue - Replace this image female.svg",
"Blue - Replace this image male.svg",
"Female no free image yet.png",
"Flag of None (square).svg",
"Flag of None.svg",
"Flag of.svg",
"Green - Replace this image female.svg",
"Green - Replace this image male.svg",
"Image is needed female.svg",
"Image is needed male.svg",
"Location map of None.svg",
"Male no free image yet.png",
"Missing flag.png",
"No flag.svg",
"No free portrait.svg",
"No portrait (female).svg",
"No portrait (male).svg",
"Red - Replace this image female.svg",
"Red - Replace this image male.svg",
"Replace this image female (blue).svg",
"Replace this image female.svg",
"Replace this image male (blue).svg",
"Replace this image male.svg",
"Silver - Replace this image female.svg",
"Silver - Replace this image male.svg",
"Replace this image.svg",
"Cricket no pic.png",
"CarersLogo.gif",
"Diagram Needed.svg",
"Example.jpg",
"Image placeholder.png",
"No male portrait.svg",
"Nocover-upload.png",
"NoDVDcover copy.png",
"Noribbon.svg",
"No portrait-BFD-test.svg",
"Placeholder barnstar ribbon.png",
"Project Trains no image.png",
"Image-request.png",
"Sin bandera.svg",
"Sin escudo.svg",
"Replace this image - temple.png",
"Replace this image butterfly.png",
"Replace this image.svg",
"Replace this image1.svg",
"Resolution angle.png",
"Image-No portrait-text-BFD-test.svg",
"Insert image here.svg",
"No image available.png",
"NO IMAGE YET square.png",
"NO IMAGE YET.png",
"No Photo Available.svg",
"No Screenshot.svg",
"No-image-available.jpg",
"Null.png",
"PictureNeeded.gif",
"Place holder.jpg",
"Unbenannt.JPG",
"UploadACopyrightFreeImage.svg",
"UploadAnImage.gif",
"UploadAnImage.svg",
"UploadAnImageShort.svg",
"CarersLogo.gif",
"Diagram Needed.svg",
"No male portrait.svg",
"NoDVDcover copy.png",
"Placeholder barnstar ribbon.png",
"Project Trains no image.png",
"Image-request.png",
}
function i.IsPlaceholder(image)
-- change underscores to spaces
image = mw.ustring.gsub(image, "_", " ");
assert(image ~= nil, 'mw.ustring.gsub(image, "_", " ") must not return nil')
-- if image starts with [[ then remove that and anything after |
if mw.ustring.sub(image,1,2) == "[[" then
image = mw.ustring.sub(image,3);
image = mw.ustring.gsub(image, "([^|]*)|.*", "%1");
assert(image ~= nil, 'mw.ustring.gsub(image, "([^|]*)|.*", "%1") must not return nil')
end
-- Trim spaces
image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
assert(image ~= nil, "mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1') must not return nil")
-- remove prefix if exists
local allNames = mw.site.namespaces[6].aliases
allNames[#allNames + 1] = mw.site.namespaces[6].name
allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
for i, name in ipairs(allNames) do
if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
break
end
end
-- Trim spaces
image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
-- capitalise first letter
image = mw.ustring.upper(mw.ustring.sub(image,1,1)) .. mw.ustring.sub(image,2);
for i,j in pairs(placeholder_image) do
if image == j then
return true
end
end
return false
end
function i.InfoboxImage(frame)
local image = frame.args["image"];
if image == "" or image == nil then
return "";
end
if image == " " then
return image;
end
if frame.args["suppressplaceholder"] ~= "no" then
if i.IsPlaceholder(image) == true then
return "";
end
end
if mw.ustring.lower(mw.ustring.sub(image,1,5)) == "http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "[http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[[http:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "https:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[https:" then
return "";
end
if mw.ustring.lower(mw.ustring.sub(image,1,8)) == "[[https:" then
return "";
end
if mw.ustring.sub(image,1,2) == "[[" then
-- search for thumbnail images and add to tracking cat if found
if mw.title.getCurrentTitle().namespace == 0 and (mw.ustring.find(image, "|%s*thumb%s*[|%]]") or mw.ustring.find(image, "|%s*thumbnail%s*[|%]]")) then
return image .. "[[Category:信息框內使用縮圖語法的頁面]]";
elseif mw.title.getCurrentTitle().namespace == 0 then
return image .. "[[Category:使用过时图像语法的页面]]";
else
return image;
end
elseif mw.ustring.sub(image,1,2) == "{{" and mw.ustring.sub(image,1,3) ~= "{{{" then
return image;
elseif mw.ustring.sub(image,1,1) == "<" then
return image;
elseif mw.ustring.sub(image,1,5) == mw.ustring.char(127).."UNIQ" then
-- Found strip marker at begining, so pass don't process at all
return image;
elseif mw.ustring.sub(image,4,9) == "`UNIQ-" then
-- Found strip marker at begining, so pass don't process at all
return image;
else
local result = "";
local page = frame.args["page"];
local size = frame.args["size"];
local maxsize = frame.args["maxsize"];
local sizedefault = frame.args["sizedefault"];
local alt = frame.args["alt"];
local link = frame.args["link"];
local title = frame.args["title"];
local border = frame.args["border"];
local upright = frame.args["upright"] or "";
local thumbtime = frame.args["thumbtime"] or "";
local center= frame.args["center"];
local class= frame.args["class"];
-- remove prefix if exists
local allNames = mw.site.namespaces[6].aliases
allNames[#allNames + 1] = mw.site.namespaces[6].name
allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
for i, name in ipairs(allNames) do
if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
break
end
end
if maxsize ~= "" and maxsize ~= nil then
-- if no sizedefault then set to maxsize
if sizedefault == "" or sizedefault == nil then
sizedefault = maxsize
end
-- check to see if size bigger than maxsize
if size ~= "" and size ~= nil then
local sizenumber = tonumber(mw.ustring.match(size,"%d*")) or 0;
local maxsizenumber = tonumber(mw.ustring.match(maxsize,"%d*")) or 0;
if sizenumber>maxsizenumber and maxsizenumber>0 then
size = maxsize;
end
end
end
-- add px to size if just a number
if (tonumber(size) or 0) > 0 then
size = size .. "px";
end
-- add px to sizedefault if just a number
if (tonumber(sizedefault) or 0) > 0 then
sizedefault = sizedefault .. "px";
end
result = "[[File:" .. image;
if page ~= "" and page ~= nil then
result = result .. "|page=" .. page;
end
if size ~= "" and size ~= nil then
result = result .. "|" .. size;
elseif sizedefault ~= "" and sizedefault ~= nil then
result = result .. "|" .. sizedefault;
else
result = result .. "|frameless";
end
if center == "yes" then
result = result .. "|center"
end
if alt ~= "" and alt ~= nil then
result = result .. "|alt=" .. alt;
end
if link ~= "" and link ~= nil then
result = result .. "|link=" .. link;
end
if border == "yes" then
result = result .. "|border";
end
if upright == "yes" then
result = result .. "|upright";
elseif upright ~= "" then
result = result .. "|upright=" .. upright;
end
if thumbtime ~= "" then
result = result .. "|thumbtime=" .. thumbtime;
end
if title ~= "" and title ~= nil then
result = result .. "|" .. title;
elseif alt ~= "" and alt ~= nil then
result = result .. "|" .. alt;
end
if class ~= "" and class ~= nil then
result = result .. "|class=" .. class;
end
result = result .. "]]";
return result;
end
end
return i;
380eaec865b1a2e3d7a275c7823a72768fbbdaa4
Template:Br separated entries
10
215
449
448
2024-08-04T12:25:22Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:Separated entries|br}}<noinclude>
{{documentation}}
</noinclude>
2019f7fc383259e70d66e43cbd97a43d20889f1b
Template:Infobox person/height
10
216
451
450
2024-08-04T12:25:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{infobox person/height/locate|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{#invoke:String|replace|<!--
-->{{{1|}}}<!--
-->|metre|m}}<!--
-->|meter|m}}<!--
-->|centi|c}}<!--
-->|feet|ft}}<!--
-->|foot|ft}}<!--
-->|inches|in}}<!--
-->|inch|in}}<!--
-->|ms|m}}<!--
-->|ins|in}}<!--
-->}}<noinclude>
{{Documentation}}
</noinclude>
8ed2c6523a6b3dbe26e7c4aa5710cb3203601bf2
Template:Infobox person/height/locate
10
217
453
452
2024-08-04T12:25:26Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{infobox person/height/switch
|{{{1|}}}
|{{#invoke:String|replace|{{{1|}}}| | }}
|m={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|m}}
|c={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|cm}}
|f={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|ft}}
|i={{#invoke:String|find|{{#invoke:String|replace|{{{1|}}}| | }}|in}}
}}<noinclude>
{{Documentation}}
</noinclude>
159e634f03c95c6d6d1362ec46f6ed6e00c94478
Template:Infobox person/height/switch
10
218
455
454
2024-08-04T12:25:27Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch:0
|{{{m}}}{{{f}}}{{{i}}}={{{1|}}}
|{{{f}}}{{{i}}}={{#ifeq:{{{c}}}|0
|{{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{m|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{m|1}}}-1}}}}|m|ftin|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{m|1}}}+1}}}}
}}
|{{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{c|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{c|1}}}-1}}}}|cm|ftin|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{m|1}}}+1}}}}
}}
}}
|{{{m}}}{{{f}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{i|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{i|1}}}-1}}}}|in|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{i|1}}}+2}}}}
}}
|{{{m}}}{{{i}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}|ft|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}}}
}}
|{{{m}}}={{#iferror:{{#expr:{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}+{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}|{{#expr:{{{i|1}}}-1}}}}}}
|{{{1|}}}
|{{convert|{{#invoke:String|sub|{{{2|0}}}|1|{{#expr:{{{f|1}}}-1}}}}|ft|{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{f|1}}}+2}}|{{#expr:{{{i|1}}}-1}}}}|in|cm|0}}{{#invoke:String|sub|{{{2|0}}}|{{#expr:{{{i|1}}}+2}}}}
}}
|{{{1|}}}
}}<noinclude>
{{Documentation}}
</noinclude>
ddea355ebb6ef35416734e310130e4ac27d50f21
Template:Remove first word
10
219
457
456
2024-08-04T12:25:27Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:String|replace|source={{{1}}}|pattern=^[^{{{sep|%s}}}]*{{{sep|%s}}}*|replace=|plain=false}}<noinclude>{{Documentation}}</noinclude>
df7a9e692f68be1581be06af5f51eaed5483b4c8
Template:Nobr
10
220
459
458
2024-08-04T12:25:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Nowrap]]
09c557cf7fa761452db419d4f4bea3707f1d9250
Template:Parameter names example
10
221
461
460
2024-08-04T12:25:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:Parameter names example|main}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
de1e29d6ebc113e9d1649ea6a976625885db8a2f
Module:Parameter names example
828
222
463
462
2024-08-04T12:25:29Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{parameter names example}}.
local p = {}
local function makeParam(s)
local lb = '{'
local rb = '}'
return lb:rep(3) .. s .. rb:rep(3)
end
local function italicize(s)
return "''" .. s .. "''"
end
local function plain(s)
return s
end
function p._main(args, frame)
-- Find how we want to format the arguments to the template.
local formatFunc
if args._display == 'italics' or args._display == 'italic' then
formatFunc = italicize
elseif args._display == 'plain' then
formatFunc = plain
else
formatFunc = makeParam
end
-- Build the table of template arguments.
local targs = {}
for k, v in pairs(args) do
if type(k) == 'number' then
targs[v] = formatFunc(v)
elseif not k:find('^_') then
targs[k] = v
end
end
--targs['nocat'] = 'yes';
--targs['categories'] = 'no';
--targs['demo'] = 'yes';
-- Find the template name.
local template
if args._template then
template = args._template
else
local currentTitle = mw.title.getCurrentTitle()
if currentTitle.prefixedText:find('/sandbox$') then
template = currentTitle.prefixedText
else
template = currentTitle.basePageTitle.prefixedText
end
end
-- Call the template with the arguments.
frame = frame or mw.getCurrentFrame()
local success, result = pcall(
frame.expandTemplate,
frame,
{title = template, args = targs}
)
if success then
return result
else
return ''
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Parameter names example'
})
return p._main(args, frame)
end
return p
fdf94fb7a5dc1fabf118d60488a02f1e65b0df24
Template:Film and Television related infobox templates
10
223
465
464
2024-08-04T12:25:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Navbox
| name = Film and Television related infobox templates
| title = 广播、电影、电视、戏剧行业相关信息框模板
| tracking = <includeonly>no</includeonly>
| bodyclass = hlist
| state = {{{state|autocollapse}}}
| above =
* [[Wikipedia:格式手册/信息框|格式手册(-{zh-hans:信息;zh-hant:資訊;}-框)]]
* [[WikiProject:维基百科/信息框工作组|维基百科专题信息框工作组]]
| group1 = 广播业
| list1 =
* [[T:廣播电台|广播电台]]
* [[T:電台節目信息框|电台节目]]
| group2 = 电影业
| list2 =
* [[T:电影信息框|电影]]
** [[T:Based on|原著]]
** [[:Category:电影产地模板|产地]]
** [[T:CFA|公映许可]]
* [[T:Infobox cinema market|电影市场]]
* [[T:Infobox film festival|电影节]]
| group3 = 电视业
| list3 = {{navbox|child|
|group1 = 平台
|list1 =
* [[T:電視網資訊|电视网]]
* [[T:电视频道信息框|电视频道]]
|group2 = 内容
|list2 =
* [[T:电视节目信息框|电视节目]]
* [[T:Infobox television season|系列節目-簡短]]
* [[T:系列节目信息框|系列节目-詳細]]
** [[T:Infobox reality competition season|真人秀比赛播出季]]
** [[T:极速前进信息框|极速前进]]
** [[T:Infobox reality music competition|真人秀音乐比赛]]
* [[T:Infobox television episode|电视剧分集]]
** [[T:Infobox Doctor Who episode|-{zh-cn:神秘博士;zh-hk:異世奇人;zh-tw:超時空奇俠;}-]]
** [[T:Infobox Futurama episode|-{zh-cn:飞出个未来;zh-hk:乃出個未來;zh-tw:飛出個未來;}-]]
** [[T:Infobox Simpsons episode|-{zh-cn:辛普森一家;zh-hk:阿森一族;zh-tw:辛普森家庭;}-]]
* [[T:Infobox machinima|引擎电影]]
* [[T:Infobox animanga/TVAnime|电视动画]]
** [[T:Infobox animanga/OVA|OVA]]
* [[T:Infobox beauty pageant|選美比賽]]
}}
| group4 = 戏剧业
| list4 =
* [[T:Infobox play|剧目]]
* [[T:马戏团信息框|马戏团]]
| group5 = 衍生产业
| list5 =
* [[T:Infobox advertising|广告]]
* [[T:Infobox podcast|播客]]
| group6 = 技术
| list6 =
* [[T:Infobox camera|相机]]
* [[T:Infobox photographic lens|镜头]]
* [[T:Infobox photographic film|胶片]]
* [[T:Infobox font|电脑字体]]
| group7 = 人物
| list7 =
* [[T:藝人|艺人]]
** [[T:AV女优|AV女优]]
** [[T:Infobox AKB48 member|AKB48集团成员]]
** [[T:Infobox Sakamichi-series member|坂道系成员]]
** [[T:Infobox SNH48 member|SNH48 Group成员]]
* [[T:Infobox YouTube personality|YouTube用户]]
* [[T:Infobox bilibili personality|哔哩哔哩用户]]
* [[T:Infobox Xigua Video personality|西瓜视-{}-频用户]]
* [[T:Infobox Douyin personality|抖音用户]]
* [[T:Infobox online streamer|网络主播]]
* [[T:Infobox vtuber|VTuber]]
| group8 = 虚构元素
| list8 =
* [[T:Infobox fictional artifact|物品]]
* [[T:Infobox character|角色]]
** [[T:Doctor Who doctor|《-{zh-cn:神秘博士;zh-hk:異世奇人;zh-tw:超時空奇俠;}-》博士]]
** [[T:火影忍者人物|火影忍者]]
** [[T:Simpsons character|-{zh-cn:辛普森一家;zh-hk:阿森一族;zh-tw:辛普森家庭;}-]]
** [[Template:原神角色|原神]]
** [[Template:崩坏:星穹铁道角色|崩坏:星穹铁道]]
** [[Template:紅樓夢人物|紅樓夢]]
* [[T:Infobox fictional location|地点]]
* [[T:Infobox fictional organisation|组织]]
* [[T:Infobox fictional race|种族]]
* [[T:虚构飞船信息框|飞船]]
| group9 = 其他
| list9 =
* [[T:Infobox media franchise|跨媒体制作]]
* [[T:Infobox award|颁奖礼]]
* [[T:Infobox awards list|奖项列表]]
* [[T:Infobox film awards|电影奖项]]
** [[T:Infobox film awards/link|-{zh-hans:链接;zh-hant:連結;}-]]
** [[T:Infobox film awards/style|格式]]
* [[T:Listen|试听]]
}}<noinclude>
{{Navbox documentation}}
[[Category:模板說明文件導航模板]]
</noinclude>
993b11816493102e877a495ec375386966e44c02
Template:Infobox Douyin personality/doc
10
224
467
466
2024-08-04T12:25:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{NoteTA|G1=MediaWiki}}{{Documentation subpage}}<!-- 在本行下編輯模板說明 -->
== 概要 ==
對於[[抖音]]平台人物的條目,此資訊框可能比{{tl|Infobox person}}模板更合適。此模板可用於抖音平台的單人或團體作者。
== 參數及使用方法 ==
=== 有基本参数的空模板 ===
{{Parameter names example|name |logo=|logo_caption |image=Pessoa Neutra.svg |caption |birth_name |birth_date |birth_place |death_date |death_place
|nationality |occupation |website
|pseudonym |channel_name |channel_display_name |years_active |genre
|subscribers |subscriber_date |views |view_date |network |associated_acts |catchphrase(s)
|silver_medal |silver_year |stats_update
}}
<pre style="overflow: auto;">
{{Infobox Douyin personality
| name =
| logo =
| logo_caption =
| image =
| caption =
| birth_name =
| birth_date =
| birth_place =
| death_date =
| death_place =
| nationality =
| occupation =
| website =
| pseudonym =
| channel_url =
| channel_display_name =
| years_active =
| genre =
| subscribers =
| subscriber_date =
| views =
| view_date =
| network =
| associated_acts =
| catchphrase(s) =
| silver_medal =
| silver_year =
| gold_medal =
| gold_year =
| stats_update =
}}
</pre>
The annotated template pattern below shows explanatory comments {{nobr|"<!--×××-->"}} about each specific parameter.
<pre style="overflow: auto;">
{{Infobox Xigua Video personality
| name =
| logo = <!-- just the filename, without the File: or Image: prefix or enclosing [[brackets]] -->
| logo_caption =
| image = <!-- just the filename, without the File: or Image: prefix or enclosing [[brackets]] -->
| caption =
| birth_name = <!-- only use if different from name -->
| birth_date = <!-- {{Birth date and age|YYYY|MM|DD}} or {{Birth-date and age|birth date†}} -->
| birth_place =
| death_date = <!-- {{Death date and age|YYYY|MM|DD|YYYY|MM|DD}} or {{Death-date and age|death date†|birth date†}} -->
| death_place =
| nationality =
| occupation =
| website =
| pseudonym = <!-- use for individuals only -->
<!-- THE FOLLOWING THREE PARAMETERS ARE INTERCHANGEABLE; DO NOT USE TWO OR MORE AT THE SAME TIME -->
| channel_url = <!-- use for channels only, format: space.Xigua Video.com/channel_url -->
| channel_display_name = <!-- if the channel's displayed name differs from the channel_name/channel_url/channel_direct_url -->
| years_active = <!-- year of channel's creation until its discontinuation or present day -->
| genre =
| subscribers =
| subscriber_date = <!-- date at which the given number of subscribers is correct -->
| views =
| view_date = <!-- date at which the given number of views is correct -->
| network = <!-- multi-channel network (MCN) to which the channel has signed (past and/or present), if any -->
| associated_acts =
| catchphrase(s) = <!-- unique phrases said by the Xigua Video uploader -->
| silver_medal = <!-- yes/no; only use if the individual/channel has been awarded with a silver medal by Xigua Video -->
| silver_year = <!-- year in which the channel reached 100,000 subscribers -->
| gold_medal = <!-- yes/no; only use if the individual/channel has been awarded with a gold medal by Xigua Video -->
| gold_year = <!-- year in which the channel reached 1,000,000 subscribers -->
| stats_update = <!-- date at which given channel statistics are correct -->
}}
† birth date and death date may be in either 'DD Month YYYY' or 'Month DD, YYYY'
</pre>
=== 完整的留空参数 ===
{{Parameter names example|header-color|honorific_prefix|name|honorific_suffix|logo|logo_size|logo_alt|logo_caption|image|image_size|alt|caption|birth_name|birth_date|birth_place|death_date|death_place|origin|nationality|education|residence|occupation|height|religion|signature|signature_size|signature_alt|website|pseudonym|channel_name|channel_url|channel_direct_url|channels|creator|location|channel_website|presenter|years_active|genre|subscribers|subscriber_date|views|view_date|network|associated_acts|catchphrase(s)|silver_medal|silver_year|module|module_personal|stats_update|extra_information|nocat}}
<pre style="overflow: auto; white-space: pre-wrap;">
{{Infobox Douyin personality
| header-color =
| honorific_prefix =
| name =
| honorific_suffix =
| logo =
| logo_size =
| logo_alt =
| logo_caption =
| image =
| image_size =
| alt =
| caption =
| birth_name =
| birth_date =
| birth_place =
| death_date =
| death_place =
| origin =
| nationality =
| education =
| residence =
| occupation =
| height =
| religion =
| partner =
| spouse =
| relatives =
| signature =
| signature_size =
| signature_alt =
| website =
| pseudonym =
| channel_url / channels =
| channel_display_name =
| location =
| channel_website =
| creator =
| presenter =
| years_active =
| genre =
| subscribers =
| subscriber_date =
| views =
| view_date =
| network =
| associated_acts =
| catchphrase(s) =
| silver_medal =
| silver_year =
| gold_medal =
| gold_year =
| module =
| module_personal =
| stats_update =
| extra_information =
}}
</pre>
{{Clear}}
== 模板编辑说明 ==
=== 模板数据 ===
{{TemplateData header}}
<templatedata>
{
"params": {
"embed": {
"label": "是否嵌入",
"description": "yes/no"
},
"honorific prefix": {
"label": "敬语前缀"
},
"name": {
"label": "名称"
},
"honorific suffix": {
"label": "敬语后缀"
},
"logo": {
"label": "徽标"
},
"logo_size": {
"label": "徽标大小"
},
"logo_alt": {
"label": "徽标的替代说明文字,给视障用户使用"
},
"logo caption": {
"label": "徽标说明"
},
"image": {
"label": "图像",
"description": "图像名称举例:abc.jpg、xpz.png、123.gif等。如果找不到合适的图像,编者可以在讨论页[[Template:WPBiography]]模板的“needs-photo”栏填写“是”。请不要在此处填写[[File:Replace this image male.svg]]、[[File:Replace this image female.svg]]或其他替代图像。建议使用自由版权图像。"
},
"image size": {
"aliases": [
"imagesize"
],
"label": "图像大小",
"description": "图像大小有如下几种写法:200px(宽度)、x300px(高度)或200x300px(最大宽度和最大长度)。留空或未定义时,会使用默认值frameless(默认为220px,但登录用户可以点击右上角的“参数设置”来调整默认缩略图尺寸)。一般情况下无需填写此参数。"
},
"imagesize": {
"aliases": [
"image size"
],
"label": "图像大小",
"description": "图像大小有如下几种写法:200px(宽度)、x300px(高度)或200x300px(最大宽度和最大长度)。留空或未定义时,会使用默认值frameless(默认为220px,但登录用户可以点击右上角的“参数设置”来调整默认缩略图尺寸)。一般情况下无需填写此参数。"
},
"alt": {
"label": "图像替代",
"description": "图像的替代文字,有助于视力缺陷用户阅读图像内容。参见[[WP:ALT]]。"
},
"image caption": {
"aliases": [
"caption"
],
"label": "图像说明"
},
"header-color": {
"description": "修改表头颜色"
},
"birth_name": {
"label": "生日"
},
"birth_date": {
"label": "出生日期"
},
"birth_place": {
"label": "出生地"
},
"death_date": {
"label": "死亡日期"
},
"death_place": {
"label": "死亡地点"
},
"height": {
"label": "高度"
},
"nationality": {
"label": "国家"
},
"residence": {
"label": "居住地"
},
"occupation": {
"label": "工作"
},
"Origin": {
"label": "出道地点"
},
"education": {
"label": "教育程度"
},
"height_m": {
"label": "身高(公尺)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。以公尺为单位填入(将会自动转换成英制单位)"
},
"height_cm": {
"label": "身高(公分)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。以公分为单位填入(将会自动转换成英制单位)。"
},
"height_ft": {
"label": "身高(英呎)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。与“身高(英吋)”同时使用(将会自动转换成国际单位)。"
},
"height_in": {
"label": "身高(剩馀英吋数字)",
"description": "如果人物知名于其身高,或者身高信息较为重要时可以填写。与“身高(英呎)”同时使用,在此填入剩馀的英吋数字(将会自动转换成国际单位)。"
},
"religion": {
"label": "宗教信仰"
},
"partner": {
"label": "伴侣"
},
"spouse": {
"description": "配偶"
},
"signature": {
"aliases": [
"签名"
],
"label": "签名",
"description": "人物签名的图像。请使用图像名称,例如:abc.jpg、xpz.png、123.gif⋯等。"
},
"signature_size": {
"label": "签名尺寸",
"description": "\t\n预设值为 150px。如有必要,签名大小可以在图像大小(\"image_size\")参数中手动调整。"
},
"signature alt": {
"label": "签名替代文字",
"description": "签名图像的替代文本。例如 File:Thomas Jefferson Signature.svg 的替代文本应为“Th: Jefferson”,使其拼写文字与图像内容完全相同。"
},
"website": {
"aliases": [
"homepage",
"URL"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"homepage": {
"aliases": [
"website",
"URL"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"URL": {
"aliases": [
"website",
"homepage"
],
"label": "网站",
"description": "仅用于官方网站。非官方网站请列于“==外部链接==”章节下。请使用 Template:URL 模板。除非伺服器需求,否则请勿包含网址中的“www”部分。某些情况下,可使用部分大写以让网址更容易阅读,例如“JaneDoe.com”。"
},
"pseudonym": {
"label": "别称"
},
"channel_name": {
"label": "频道名称"
},
"channel_url": {
"label": "频道编号"
},
"channel_direct_url": {
"label": "频道编号"
},
"years active": {
"aliases": [
"yearsactive"
],
"label": "活跃时期"
},
"genre": {
"label": "类型"
},
"subscribers": {
"label": "粉丝数"
},
"views": {
"label": "总播放量"
},
"network": {
"label": "包装公司"
},
"associated_acts": {
"label": "相关团体"
},
"catchphrase(s)": {
"label": "口头禅"
},
"channels": {
"label": "频道名称"
},
"creator": {
"label": "创办人"
},
"subscriber_date": {
"label": "粉丝数截止日期"
},
"view_date": {
"label": "统计播放量的截止日期"
},
"stats_update": {
"label": "统计更新时间"
},
"extra_information": {},
"nocat": {},
"Praise quantity": {
"label": "点赞量"
},
"Praise quantity_date": {
"label": "点赞量截止日期"
}
}
}
</templatedata>
{{Film and Television related infobox templates}}
<includeonly>{{Sandbox other||<!-- 本行下加入模板的分類 -->
[[Category:人物信息框模板]]
}}</includeonly>
11a3285c2b943a9fce4eaf3182d3120ff86a62d5
那艺娜
0
171
468
345
2024-08-04T12:37:10Z
黑茶
2
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref>[https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4]QQ音乐</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>[https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta]</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
50373b233b23f3dde503939c452800c468ff4fc0
507
468
2024-08-04T12:46:47Z
黑茶
2
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref>[https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4]QQ音乐</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>[https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta]</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 参考资料 ==
{{Reflist}}
b57547c311eb5bdc819a36d6a9f625c5bb53552a
Template:Birth date and age
10
225
470
469
2024-08-04T12:41:21Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><span style="display:none"> (<span class="bday">{{{1|{{{year}}}}}}-{{padleft:{{{2|{{{month}}}}}}|2|0}}-{{padleft:{{{3|{{{day}}}}}}|2|0}}</span>) </span>{{{1|{{{year}}}}}}年{{#if:{{{df|}}}|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日}}<span class="noprint ForceAgeToShow">({{age | {{{1|{{{year}}}}}} | {{{2|{{{month}}}}}} | {{{3|{{{day}}}}}} }}歲)</span></includeonly><noinclude>
{{documentation|Template:Birth date and age/doc}}
</noinclude>
42ca66b5d055e872542b96690c44bd8f7e691dec
Template:Age
10
226
472
471
2024-08-04T12:41:22Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:age|age_generic|template=age_full_years}}<noinclude>{{documentation}}</noinclude>
0bb21e2a735de3813c6688d5c260c5596c9cee37
Module:Age
828
227
474
473
2024-08-04T12:41:22Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- Implement various "age of" and other date-related templates.
local _Date, _currentDate
local function getExports(frame)
-- Return objects exported from the date module or its sandbox.
if not _Date then
local sandbox = frame:getTitle():find('sandbox', 1, true) and '/sandbox' or ''
local datemod = require('Module:Date' .. sandbox)
_Date = datemod._Date
_currentDate = datemod._current
end
return _Date, _currentDate
end
local Collection -- a table to hold items
Collection = {
add = function (self, item)
if item ~= nil then
self.n = self.n + 1
self[self.n] = item
end
end,
join = function (self, sep)
return table.concat(self, sep)
end,
remove = function (self, pos)
if self.n > 0 and (pos == nil or (0 < pos and pos <= self.n)) then
self.n = self.n - 1
return table.remove(self, pos)
end
end,
sort = function (self, comp)
table.sort(self, comp)
end,
new = function ()
return setmetatable({n = 0}, Collection)
end
}
Collection.__index = Collection
local function stripToNil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (which may, for example, be nil).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local yes = require('Module:Yesno')
local function message(msg, id)
-- Return formatted message text for an error or warning.
local categories = {
error = '[[Category:Age模块错误]]',
warning = '[[Category:Age模块错误]]', -- same as error until determine whether 'Age warning' would be worthwhile
}
local a, b, category
if id == 'warning' then
a = '<sup>[<i>'
b = '</i>]</sup>'
else
a = '<strong class="error">错误:'
b = '</strong>'
end
if mw.title.getCurrentTitle():inNamespaces(0) then
-- Category only in namespaces: 0=article.
category = categories[id or 'error']
end
return
a ..
mw.text.nowiki(msg) ..
b ..
(category or '')
end
local function formatNumber(number)
-- Return the given number formatted with commas as group separators,
-- given that the number is an integer.
local numstr = tostring(number)
local length = #numstr
local places = Collection.new()
local pos = 0
repeat
places:add(pos)
pos = pos + 3
until pos >= length
places:add(length)
local groups = Collection.new()
for i = places.n, 2, -1 do
local p1 = length - places[i] + 1
local p2 = length - places[i - 1]
groups:add(numstr:sub(p1, p2))
end
return groups:join(',')
end
local function spellNumber(number, options, i)
-- Return result of spelling number, or
-- return number (as a string) if cannot spell it.
-- i == 1 for the first number which can optionally start with an uppercase letter.
number = tostring(number)
return require('Module:ConvertNumeric').spell_number(
number,
nil, -- fraction numerator
nil, -- fraction denominator
i == 1 and options.upper, -- true: 'One' instead of 'one'
not options.us, -- true: use 'and' between tens/ones etc
options.adj, -- true: hyphenated
options.ordinal -- true: 'first' instead of 'one'
) or number
end
local function makeSort(value, sortable)
-- Return a sort key if requested.
-- Assume value is a valid number which has not overflowed.
if sortable == 'sortable_table' or sortable == 'sortable_on' or sortable == 'sortable_debug' then
local sortkey
if value == 0 then
sortkey = '5000000000000000000'
else
local mag = math.floor(math.log10(math.abs(value)) + 1e-14)
local prefix
if value > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
value = value + 10^(mag+1)
end
sortkey = string.format('%d', prefix) .. string.format('%015.0f', math.floor(value * 10^(14-mag)))
end
local lhs, rhs
if sortable == 'sortable_table' then
lhs = 'data-sort-value="'
rhs = '"|'
else
lhs = sortable == 'sortable_debug' and
'<span style="border:1px solid;display:inline;" class="sortkey">' or
'<span style="display:none" class="sortkey">'
rhs = '♠</span>'
end
return lhs .. sortkey .. rhs
end
end
local translateParameters = {
abbr = {
off = 'abbr_off',
on = 'abbr_on',
},
disp = {
age = 'disp_age',
raw = 'disp_raw',
},
format = {
raw = 'format_raw',
commas = 'format_commas',
},
round = {
on = 'on',
yes = 'on',
months = 'ym',
weeks = 'ymw',
days = 'ymd',
hours = 'ymdh',
},
sep = {
comma = 'sep_comma',
[','] = 'sep_comma',
serialcomma = 'sep_serialcomma',
space = 'sep_space',
},
show = {
hide = { id = 'hide' },
y = { 'y', id = 'y' },
ym = { 'y', 'm', id = 'ym' },
ymd = { 'y', 'm', 'd', id = 'ymd' },
ymw = { 'y', 'm', 'w', id = 'ymw' },
ymwd = { 'y', 'm', 'w', 'd', id = 'ymwd' },
yd = { 'y', 'd', id = 'yd', keepZero = true },
m = { 'm', id = 'm' },
md = { 'm', 'd', id = 'md' },
w = { 'w', id = 'w' },
wd = { 'w', 'd', id = 'wd' },
h = { 'H', id = 'h' },
hm = { 'H', 'M', id = 'hm' },
hms = { 'H', 'M', 'S', id = 'hms' },
d = { 'd', id = 'd' },
dh = { 'd', 'H', id = 'dh' },
dhm = { 'd', 'H', 'M', id = 'dhm' },
dhms = { 'd', 'H', 'M', 'S', id = 'dhms' },
ymdh = { 'y', 'm', 'd', 'H', id = 'ymdh' },
ymdhm = { 'y', 'm', 'd', 'H', 'M', id = 'ymdhm' },
ymwdh = { 'y', 'm', 'w', 'd', 'H', id = 'ymwdh' },
ymwdhm = { 'y', 'm', 'w', 'd', 'H', 'M', id = 'ymwdhm' },
},
sortable = {
off = false,
on = 'sortable_on',
table = 'sortable_table',
debug = 'sortable_debug',
},
}
local spellOptions = {
cardinal = {},
Cardinal = { upper = true },
cardinal_us = { us = true },
Cardinal_us = { us = true, upper = true },
ordinal = { ordinal = true },
Ordinal = { ordinal = true, upper = true },
ordinal_us = { ordinal = true, us = true },
Ordinal_us = { ordinal = true, us = true, upper = true },
}
local function dateExtract(frame)
-- Return part of a date after performing an optional operation.
local Date = getExports(frame)
local args = frame:getParent().args
local parms = {}
for i, v in ipairs(args) do
parms[i] = v
end
if yes(args.fix) then
table.insert(parms, 'fix')
end
if yes(args.partial) then
table.insert(parms, 'partial')
end
local show = stripToNil(args.show) or 'dmy'
local date = Date(unpack(parms))
if not date then
if show == 'format' then
return 'error'
end
return message('需要有效的日期')
end
local add = stripToNil(args.add)
if add then
for item in add:gmatch('%S+') do
date = date + item
if not date then
return message('无法添加“' .. item .. '”')
end
end
end
local prefix, result
local sortable = translateParameters.sortable[args.sortable]
if sortable then
local value = (date.partial and date.partial.first or date).jdz
prefix = makeSort(value, sortable)
end
if show ~= 'hide' then
result = date[show]
if result == nil then
result = date:text(show)
elseif type(result) == 'boolean' then
result = result and '1' or '0'
else
result = tostring(result)
end
end
return (prefix or '') .. (result or '')
end
local function rangeJoin(range)
-- Return text to be used between a range of ages.
return range == 'dash' and '—' or '或'
end
local function makeText(values, components, names, options, noUpper)
-- Return wikitext representing an age or duration.
local text = Collection.new()
local count = #values
local sep = names.sep or ''
for i, v in ipairs(values) do
-- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years).
local islist = type(v) == 'table'
if (islist or v > 0) or (text.n == 0 and i == count) or (text.n > 0 and components.keepZero) then
local fmt, vstr
if options.spell then
fmt = function(number)
return spellNumber(number, options.spell, noUpper or i)
end
elseif i == 1 and options.format == 'format_commas' then
-- Numbers after the first should be small and not need formatting.
fmt = formatNumber
else
fmt = tostring
end
if islist then
vstr = fmt(v[1]) .. rangeJoin(options.range)
noUpper = true
vstr = vstr .. fmt(v[2])
else
vstr = fmt(v)
end
local name = names[components[i]]
if name then
local plural = names.plural
if not plural or (islist and v[2] or v) == 1 then
plural = ''
end
text:add(vstr .. sep .. name .. plural)
else
text:add(vstr)
end
end
end
local first, last
-- hh mm ss
if options.join == 'sep_space' then
first = ' '
last = ' '
-- hh时,mm分,ss秒
elseif options.join == 'sep_comma' then
first = ','
last = ','
-- hh时,mm分又ss秒
elseif options.join == 'sep_serialcomma' then
first = ','
last = text.n > 2 and (names.y == '年' and '又' or '零') or ','
-- hh时mm分ss秒
elseif options.join == 'sep_none' then
first = ''
last = ''
-- hh时mm分又ss秒
else -- 'sep_serial'
first = ''
last = text.n > 2 and (names.y == '年' and '又' or '零') or ''
end
for i, v in ipairs(text) do
if i < text.n then
text[i] = v .. (i + 1 < text.n and first or last)
end
end
local sign = ''
if options.isnegative then
-- Do not display negative zero.
if text.n > 1 or (text.n == 1 and text[1]:sub(1, 1) ~= '0' ) then
if options.format == 'format_raw' then
sign = '-' -- plain hyphen so result can be used in a calculation
else
sign = '−' -- Unicode U+2212 MINUS SIGN
end
end
end
return
(options.prefix or '') ..
(options.extra or '') ..
sign ..
text:join() ..
(options.suffix or '')
end
local function dateDifference(parms)
-- Return a formatted date difference using the given parameters
-- which have been validated.
local names = {
abbr_off = {
plural = '',
sep = '',
y = '年',
m = '个月',
w = '周',
d = '天',
H = '小时',
M = '分',
S = '秒',
},
abbr_on = {
y = 'y',
m = 'm',
w = 'w',
d = 'd',
H = 'h',
M = 'm',
S = 's',
},
abbr_age = {
plural = '',
sep = '',
y = '岁',
m = '个月',
w = '周',
d = '天',
H = '小时',
M = '分',
S = '秒',
},
abbr_raw = {},
}
local diff = parms.diff -- must be a valid date difference
local show = parms.show -- may be nil; default is set below
local abbr = parms.abbr or 'abbr_off'
local defaultJoin -- 中文应该全为nil
if abbr ~= 'abbr_off' then
defaultJoin = nil
end
if not show then
show = 'ymd'
if parms.disp == 'disp_age' then
if diff.years < 3 then
defaultJoin = nil
if diff.years >= 1 then
show = 'ym'
else
show = 'md'
end
else
show = 'y'
end
end
end
if type(show) ~= 'table' then
show = translateParameters.show[show]
end
if parms.disp == 'disp_raw' then
defaultJoin = 'sep_space'
abbr = 'abbr_raw'
elseif parms.wantSc then
defaultJoin = 'sep_serialcomma'
end
local diffOptions = {
round = parms.round,
duration = parms.wantDuration,
range = parms.range and true or nil,
}
local prefix
if parms.sortable then
local value = diff.age_days + (parms.wantDuration and 1 or 0) -- days and fraction of a day
if diff.isnegative then
value = -value
end
prefix = makeSort(value, parms.sortable)
end
local textOptions = {
prefix = prefix,
suffix = parms.suffix, -- not currently used
extra = parms.extra,
format = parms.format,
join = parms.sep or defaultJoin,
isnegative = diff.isnegative,
range = parms.range,
spell = parms.spell,
}
if show.id == 'hide' then
return prefix or ''
end
local values = { diff:age(show.id, diffOptions) }
if values[1] then
return makeText(values, show, names[abbr], textOptions)
end
if diff.partial then
-- Handle a more complex range such as
-- {{age_yd|20 Dec 2001|2003|range=yes}} → 1 year, 12 days or 2 years, 11 days
local opt = {
format = textOptions.format,
join = textOptions.join,
isnegative = textOptions.isnegative,
spell = textOptions.spell,
}
return
(textOptions.prefix or '') ..
makeText({ diff.partial.mindiff:age(show.id, diffOptions) }, show, names[abbr], opt) ..
rangeJoin(textOptions.range) ..
makeText({ diff.partial.maxdiff:age(show.id, diffOptions) }, show, names[abbr], opt, true) ..
(textOptions.suffix or '')
end
return message('此处不支持参数show=' .. show.id)
end
local function getDates(frame, getopt)
-- Parse template parameters and return one of:
-- * date (a date table, if single)
-- * date1, date2 (two date tables, if not single)
-- * text (a string error message)
-- A missing date is optionally replaced with the current date.
-- If wantMixture is true, a missing date component is replaced
-- from the current date, so can get a bizarre mixture of
-- specified/current y/m/d as has been done by some "age" templates.
-- Some results may be placed in table getopt.
local Date, currentDate = getExports(frame)
getopt = getopt or {}
local function flagCurrent(text)
-- This allows the calling template to detect if the current date has been used,
-- that is, whether both dates have been entered in a template expecting two.
-- For example, an infobox may want the age when an event occurred, not the current age.
-- Don't bother detecting if wantMixture is used because not needed and it is a poor option.
if not text then
text = 'currentdate'
if getopt.flag == 'usesCurrent' then
getopt.usesCurrent = true
end
end
return text
end
local args = frame:getParent().args
local fields = {}
local isNamed = args.year or args.year1 or args.year2 or
args.month or args.month1 or args.month2 or
args.day or args.day1 or args.day2
if isNamed then
fields[1] = args.year1 or args.year
fields[2] = args.month1 or args.month
fields[3] = args.day1 or args.day
fields[4] = args.year2
fields[5] = args.month2
fields[6] = args.day2
else
for i = 1, 6 do
fields[i] = args[i]
end
end
local imax = 0
for i = 1, 6 do
fields[i] = stripToNil(fields[i])
if fields[i] then
imax = i
end
if getopt.omitZero and i % 3 ~= 1 then -- omit zero months and days as unknown values but keep year 0 which is 1 BCE
if tonumber(fields[i]) == 0 then
fields[i] = nil
getopt.partial = true
end
end
end
local fix = getopt.fix and 'fix' or ''
local noDefault = imax == 0 and getopt.noMissing
local partialText = getopt.partial and 'partial' or ''
local dates = {}
if isNamed or imax >= 3 then
local nrDates = getopt.single and 1 or 2
if getopt.wantMixture then
-- Cannot be partial since empty fields are set from current.
local components = { 'year', 'month', 'day' }
for i = 1, nrDates * 3 do
fields[i] = fields[i] or currentDate[components[i > 3 and i - 3 or i]]
end
for i = 1, nrDates do
local index = i == 1 and 1 or 4
dates[i] = Date(fields[index], fields[index+1], fields[index+2])
end
else
-- If partial dates are allowed, accept
-- year only, or
-- year and month only
-- Do not accept year and day without a month because that makes no sense
-- (and because, for example, Date('partial', 2001, nil, 12) sets day = nil, not 12).
for i = 1, nrDates do
local index = i == 1 and 1 or 4
local y, m, d = fields[index], fields[index+1], fields[index+2]
if (getopt.partial and y and (m or not d)) or (y and m and d) then
dates[i] = Date(fix, partialText, y, m, d)
elseif not y and not m and not d and not noDefault then
dates[i] = Date(flagCurrent())
end
end
end
elseif not noDefault then
getopt.textdates = true -- have parsed each date from a single text field
dates[1] = Date(fix, partialText, flagCurrent(fields[1]))
if not getopt.single then
dates[2] = Date(fix, partialText, flagCurrent(fields[2]))
end
end
if not dates[1] then
return message('需要有效的年月日')
end
if getopt.single then
return dates[1]
end
if not dates[2] then
return message('第二个日期应该是年月日')
end
return dates[1], dates[2]
end
local function ageGeneric(frame)
-- Return the result required by the specified template.
-- Can use sortable=x where x = on/table/off/debug in any supported template.
-- Some templates default to sortable=on but can be overridden.
local name = frame.args.template
if not name then
return message('调用它的模板必须有“|template=x”参数,其中x是所需的操作')
end
local args = frame:getParent().args
local specs = {
-- 重点!切勿随意更改!
age_days = { -- {{age in days}}
show = 'd',
disp = 'disp_raw',
},
age_days_nts = { -- {{age in days nts}}
show = 'd',
disp = 'disp_raw',
format = 'format_commas',
sortable = 'on',
},
duration_days = { -- {{duration in days}}
show = 'd',
disp = 'disp_raw',
duration = true,
},
duration_days_nts = { -- {{duration in days nts}}
show = 'd',
disp = 'disp_raw',
format = 'format_commas',
sortable = 'on',
duration = true,
},
age_full_years = { -- {{age}}
show = 'y',
abbr = 'abbr_raw',
flag = 'usesCurrent',
omitZero = true,
range = 'no',
},
age_full_years_nts = { -- {{age nts}}
show = 'y',
abbr = 'abbr_raw',
format = 'format_commas',
sortable = 'on',
},
age_in_years = { -- {{age in years}}
show = 'y',
abbr = 'abbr_raw',
negative = 'error',
range = 'dash',
},
age_in_years_nts = { -- {{age in years nts}}
show = 'y',
abbr = 'abbr_raw',
negative = 'error',
range = 'dash',
format = 'format_commas',
sortable = 'on',
},
age_infant = { -- {{age for infant}}
-- Do not set show because special processing is done later.
abbr = 'abbr_off',
disp = 'disp_age',
sortable = 'on',
age = true,
},
age_m = { -- {{age in months}}
show = 'm',
disp = 'disp_raw',
},
age_w = { -- {{age in weeks}}
show = 'w',
disp = 'disp_raw',
},
age_wd = { -- {{age in weeks and days}}
show = 'wd',
},
age_yd = { -- {{age in years and days}}
show = 'yd',
format = 'format_commas',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
age = true,
},
age_yd_nts = { -- {{age in years and days nts}}
show = 'yd',
format = 'format_commas',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
sortable = 'on',
age = true,
},
age_ym = { -- {{age in years and months}}
show = 'ym',
sep = args.sep == 'and' and 'sep_serialcomma' or nil,
},
age_ymd = { -- {{age in years, months and days}}
show = 'ymd',
range = 'dash',
},
age_ymwd = { -- {{age in years, months, weeks and days}}
show = 'ymwd',
wantMixture = true,
},
}
local spec = specs[name]
if not spec then
return message('指定的模板名称无效')
end
if name == 'age_days' then
local su = stripToNil(args['show unit'])
if su then
if su == 'abbr' or su == 'full' then
spec.disp = nil
spec.abbr = su == 'abbr' and 'abbr_on' or nil
end
end
end
local partial, autofill
local range = stripToNil(args.range) or spec.range
if range then
-- Suppose partial dates are used and age could be 11 or 12 years.
-- "|range=" (empty value) has no effect (spec is used).
-- "|range=yes" or spec.range == true sets range = true (gives "11或12")
-- "|range=dash" or spec.range == 'dash' sets range = 'dash' (gives "11—12").
-- "|range=no" or spec.range == 'no' sets range = nil and fills each date in the diff (gives "12").
-- ("on" is equivalent to "yes", and "off" is equivalent to "no").
-- "|range=OTHER" sets range = nil and rejects partial dates.
range = ({ dash = 'dash', off = 'no', no = 'no', [true] = true })[range] or yes(range)
if range then
partial = true -- accept partial dates with a possible age range for the result
if range == 'no' then
autofill = true -- missing month/day in first or second date are filled from other date or 1
range = nil
end
end
end
local getopt = {
fix = yes(args.fix),
flag = stripToNil(args.flag) or spec.flag,
omitZero = spec.omitZero,
partial = partial,
wantMixture = spec.wantMixture,
}
local date1, date2 = getDates(frame, getopt)
if type(date1) == 'string' then
return date1
end
local useAge = spec.age
if args.age ~= nil then
useAge = yes(args.age, spec.age)
end
local format = stripToNil(args.format)
local spell = spellOptions[format]
if format then
format = 'format_' .. format
elseif name == 'age_days' and getopt.textdates then
format = 'format_commas'
end
local parms = {
diff = date2:subtract(date1, { fill = autofill }),
wantDuration = spec.duration or yes(args.duration),
range = range,
wantSc = yes(args.sc),
show = args.show == 'hide' and 'hide' or spec.show,
abbr = useAge and 'abbr_age' or spec.abbr,
disp = spec.disp,
extra = (getopt.usesCurrent and format ~= 'format_raw') and '<span class="currentage"></span>' or nil,
format = format or spec.format,
round = yes(args.round),
sep = spec.sep,
sortable = translateParameters.sortable[args.sortable or spec.sortable],
spell = spell,
}
if (spec.negative or frame.args.negative) == 'error' and parms.diff.isnegative then
return message('第二个日期不应该在第一个日期之前')
end
return dateDifference(parms)
end
local function bda(frame)
-- Implement [[Template:Birth date and age]].
local args = frame:getParent().args
local options = { noMissing=true, single=true }
local date = getDates(frame, options)
if type(date) == 'string' then
return date -- error text
end
local Date = getExports(frame)
local diff = Date('currentdate') - date
if diff.isnegative or diff.years > 150 then
return message('计算年龄所需的出生日期无效')
end
local disp, show = 'disp_raw', 'y'
if diff.years < 2 then
disp = 'disp_age'
if diff.years == 0 and diff.months == 0 then
show = 'd'
else
show = 'm'
end
end
local result = '%-Y年%B月%-d日'
result = '(<span class="bday">%-Y-%m-%d</span>) </span>' .. result
result = '<span style="display:none"> ' ..
date:text(result) ..
'<span class="noprint ForceAgeToShow"> ' ..
'(' ..
dateDifference({
diff = diff,
show = show,
abbr = 'abbr_off',
disp = disp,
sep = 'sep_space',
}) ..
')</span>'
local warnings = tonumber(frame.args.warnings)
if warnings and warnings > 0 then
local good = {
df = true,
mf = true,
day = true,
day1 = true,
month = true,
month1 = true,
year = true,
year1 = true,
}
local invalid
local imax = options.textdates and 1 or 3
for k, _ in pairs(args) do
if type(k) == 'number' then
if k > imax then
invalid = tostring(k)
break
end
else
if not good[k] then
invalid = k
break
end
end
end
if invalid then
result = result .. message(invalid .. '参数无效', 'warning')
end
end
return result
end
local function dateToGsd(frame)
-- Implement [[Template:Gregorian serial date]].
-- Return Gregorian serial date of the given date, or the current date.
-- The returned value is negative for dates before 1 January 1 AD
-- despite the fact that GSD is not defined for such dates.
local date = getDates(frame, { wantMixture=true, single=true })
if type(date) == 'string' then
return date
end
return tostring(date.gsd)
end
local function jdToDate(frame)
-- Return formatted date from a Julian date.
-- The result includes a time if the input includes a fraction.
-- The word 'Julian' is accepted for the Julian calendar.
local Date = getExports(frame)
local args = frame:getParent().args
local date = Date('juliandate', args[1], args[2])
if date then
return date:text()
end
return message('需要有效的儒略历日期')
end
local function dateToJd(frame)
-- Return Julian date (a number) from a date which may include a time,
-- or the current date ('currentdate') or current date and time ('currentdatetime').
-- The word 'Julian' is accepted for the Julian calendar.
local Date = getExports(frame)
local args = frame:getParent().args
local date = Date(args[1], args[2], args[3], args[4], args[5], args[6], args[7])
if date then
return tostring(date.jd)
end
return message('需要有效的年/月/日或“currentdate”(当前)')
end
local function timeInterval(frame)
-- Implement [[Template:Time interval]].
-- There are two positional arguments: date1, date2.
-- The default for each is the current date and time.
-- Result is date2 - date1 formatted.
local Date = getExports(frame)
local args = frame:getParent().args
local parms = {
wantDuration = yes(args.duration),
range = yes(args.range) or (args.range == 'dash' and 'dash' or nil),
wantSc = yes(args.sc),
}
local fix = yes(args.fix) and 'fix' or ''
local date1 = Date(fix, 'partial', stripToNil(args[1]) or 'currentdatetime')
if not date1 then
return message('第一个参数中的开始日期无效')
end
local date2 = Date(fix, 'partial', stripToNil(args[2]) or 'currentdatetime')
if not date2 then
return message('第二个参数中的结束日期无效')
end
parms.diff = date2 - date1
for argname, translate in pairs(translateParameters) do
local parm = stripToNil(args[argname])
if parm then
parm = translate[parm]
if parm == nil then -- test for nil because false is a valid setting
return message('参数' .. argname .. '=' .. args[argname] .. '无效')
end
parms[argname] = parm
end
end
if parms.round then
local round = parms.round
local show = parms.show
if round ~= 'on' then
if show then
if show.id ~= round then
return message('参数show=' .. args.show .. '与round=' .. args.round .. '冲突')
end
else
parms.show = translateParameters.show[round]
end
end
parms.round = true
end
return dateDifference(parms)
end
return {
age_generic = ageGeneric, -- can emulate several age templates
birth_date_and_age = bda, -- Template:Birth_date_and_age
gsd = dateToGsd, -- Template:Gregorian_serial_date
extract = dateExtract, -- Template:Extract
jd_to_date = jdToDate, -- Template:?
JULIANDAY = dateToJd, -- Template:JULIANDAY
time_interval = timeInterval, -- Template:Time_interval
}
e3336fa0f7d460d6f03e7ba089b8b58632a537e8
Module:Date
828
228
476
475
2024-08-04T12:41:23Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- Date functions for use by other modules.
-- I18N and time zones are not supported.
local MINUS = '−' -- Unicode U+2212 MINUS SIGN
local floor = math.floor
local Date, DateDiff, diffmt -- forward declarations
local uniq = { 'unique identifier' }
local function is_date(t)
-- The system used to make a date read-only means there is no unique
-- metatable that is conveniently accessible to check.
return type(t) == 'table' and t._id == uniq
end
local function is_diff(t)
return type(t) == 'table' and getmetatable(t) == diffmt
end
local function _list_join(list, sep)
return table.concat(list, sep)
end
local function collection()
-- Return a table to hold items.
return {
n = 0,
add = function (self, item)
self.n = self.n + 1
self[self.n] = item
end,
join = _list_join,
}
end
local function strip_to_nil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (convenient when Date fields are provided from
-- another module which may pass a string, a number, or another type).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local function is_leap_year(year, calname)
-- Return true if year is a leap year.
if calname == 'Julian' then
return year % 4 == 0
end
return (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0
end
local function days_in_month(year, month, calname)
-- Return number of days (1..31) in given month (1..12).
if month == 2 and is_leap_year(year, calname) then
return 29
end
return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month]
end
local function h_m_s(time)
-- Return hour, minute, second extracted from fraction of a day.
time = floor(time * 24 * 3600 + 0.5) -- number of seconds
local second = time % 60
time = floor(time / 60)
return floor(time / 60), time % 60, second
end
local function hms(date)
-- Return fraction of a day from date's time, where (0 <= fraction < 1)
-- if the values are valid, but could be anything if outside range.
return (date.hour + (date.minute + date.second / 60) / 60) / 24
end
local function julian_date(date)
-- Return jd, jdz from a Julian or Gregorian calendar date where
-- jd = Julian date and its fractional part is zero at noon
-- jdz = same, but assume time is 00:00:00 if no time given
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- Testing shows this works for all dates from year -9999 to 9999!
-- JDN 0 is the 24-hour period starting at noon UTC on Monday
-- 1 January 4713 BC = (-4712, 1, 1) Julian calendar
-- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar
local offset
local a = floor((14 - date.month)/12)
local y = date.year + 4800 - a
if date.calendar == 'Julian' then
offset = floor(y/4) - 32083
else
offset = floor(y/4) - floor(y/100) + floor(y/400) - 32045
end
local m = date.month + 12*a - 3
local jd = date.day + floor((153*m + 2)/5) + 365*y + offset
if date.hastime then
jd = jd + hms(date) - 0.5
return jd, jd
end
return jd, jd - 0.5
end
local function set_date_from_jd(date)
-- Set the fields of table date from its Julian date field.
-- Return true if date is valid.
-- http://www.tondering.dk/claus/cal/julperiod.php#formula
-- This handles the proleptic Julian and Gregorian calendars.
-- Negative Julian dates are not defined but they work.
local calname = date.calendar
local low, high -- min/max limits for date ranges −9999-01-01 to 9999-12-31
if calname == 'Gregorian' then
low, high = -1930999.5, 5373484.49999
elseif calname == 'Julian' then
low, high = -1931076.5, 5373557.49999
else
return
end
local jd = date.jd
if not (type(jd) == 'number' and low <= jd and jd <= high) then
return
end
local jdn = floor(jd)
if date.hastime then
local time = jd - jdn -- 0 <= time < 1
if time >= 0.5 then -- if at or after midnight of next day
jdn = jdn + 1
time = time - 0.5
else
time = time + 0.5
end
date.hour, date.minute, date.second = h_m_s(time)
else
date.second = 0
date.minute = 0
date.hour = 0
end
local b, c
if calname == 'Julian' then
b = 0
c = jdn + 32082
else -- Gregorian
local a = jdn + 32044
b = floor((4*a + 3)/146097)
c = a - floor(146097*b/4)
end
local d = floor((4*c + 3)/1461)
local e = c - floor(1461*d/4)
local m = floor((5*e + 2)/153)
date.day = e - floor((153*m + 2)/5) + 1
date.month = m + 3 - 12*floor(m/10)
date.year = 100*b + d - 4800 + floor(m/10)
return true
end
local function fix_numbers(numbers, y, m, d, H, M, S, partial, hastime, calendar)
-- Put the result of normalizing the given values in table numbers.
-- The result will have valid m, d values if y is valid; caller checks y.
-- The logic of PHP mktime is followed where m or d can be zero to mean
-- the previous unit, and -1 is the one before that, etc.
-- Positive values carry forward.
local date
if not (1 <= m and m <= 12) then
date = Date(y, 1, 1)
if not date then return end
date = date + ((m - 1) .. 'm')
y, m = date.year, date.month
end
local days_hms
if not partial then
if hastime and H and M and S then
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
days_hms = hms({ hour = H, minute = M, second = S })
end
end
if days_hms or not (1 <= d and d <= days_in_month(y, m, calendar)) then
date = date or Date(y, m, 1)
if not date then return end
date = date + (d - 1 + (days_hms or 0))
y, m, d = date.year, date.month, date.day
if days_hms then
H, M, S = date.hour, date.minute, date.second
end
end
end
numbers.year = y
numbers.month = m
numbers.day = d
if days_hms then
-- Don't set H unless it was valid because a valid H will set hastime.
numbers.hour = H
numbers.minute = M
numbers.second = S
end
end
local function set_date_from_numbers(date, numbers, options)
-- Set the fields of table date from numeric values.
-- Return true if date is valid.
if type(numbers) ~= 'table' then
return
end
local y = numbers.year or date.year
local m = numbers.month or date.month
local d = numbers.day or date.day
local H = numbers.hour
local M = numbers.minute or date.minute or 0
local S = numbers.second or date.second or 0
local need_fix
if y and m and d then
date.partial = nil
if not (-9999 <= y and y <= 9999 and
1 <= m and m <= 12 and
1 <= d and d <= days_in_month(y, m, date.calendar)) then
if not date.want_fix then
return
end
need_fix = true
end
elseif y and date.partial then
if d or not (-9999 <= y and y <= 9999) then
return
end
if m and not (1 <= m and m <= 12) then
if not date.want_fix then
return
end
need_fix = true
end
else
return
end
if date.partial then
H = nil -- ignore any time
M = nil
S = nil
else
if H then
-- It is not possible to set M or S without also setting H.
date.hastime = true
else
H = 0
end
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
if date.want_fix then
need_fix = true
else
return
end
end
end
date.want_fix = nil
if need_fix then
fix_numbers(numbers, y, m, d, H, M, S, date.partial, date.hastime, date.calendar)
return set_date_from_numbers(date, numbers, options)
end
date.year = y -- -9999 to 9999 ('n BC' → year = 1 - n)
date.month = m -- 1 to 12 (may be nil if partial)
date.day = d -- 1 to 31 (* = nil if partial)
date.hour = H -- 0 to 59 (*)
date.minute = M -- 0 to 59 (*)
date.second = S -- 0 to 59 (*)
if type(options) == 'table' then
for _, k in ipairs({ 'am', 'era', 'format' }) do
if options[k] then
date.options[k] = options[k]
end
end
end
return true
end
local function make_option_table(options1, options2)
-- If options1 is a string, return a table with its settings, or
-- if it is a table, use its settings.
-- Missing options are set from table options2 or defaults.
-- If a default is used, a flag is set so caller knows the value was not intentionally set.
-- Valid option settings are:
-- am: 'am', 'a.m.', 'AM', 'A.M.'
-- 'pm', 'p.m.', 'PM', 'P.M.' (each has same meaning as corresponding item above)
-- era: 'BCMINUS', 'BCNEGATIVE', 'BC', 'B.C.', 'BCE', 'B.C.E.', 'AD', 'A.D.', 'CE', 'C.E.'
-- Option am = 'am' does not mean the hour is AM; it means 'am' or 'pm' is used, depending on the hour,
-- and am = 'pm' has the same meaning.
-- Similarly, era = 'BC' means 'BC' is used if year <= 0.
-- BCMINUS displays a MINUS if year < 0 and the display format does not include %{era}.
-- BCNEGATIVE is similar but displays a hyphen.
local result = { bydefault = {} }
if type(options1) == 'table' then
result.am = options1.am
result.era = options1.era
elseif type(options1) == 'string' then
-- Example: 'am:AM era:BC' or 'am=AM era=BC'.
for item in options1:gmatch('%S+') do
local lhs, rhs = item:match('^(%w+)[:=](.+)$')
if lhs then
result[lhs] = rhs
end
end
end
options2 = type(options2) == 'table' and options2 or {}
local defaults = { am = 'am', era = 'BC' }
for k, v in pairs(defaults) do
if not result[k] then
if options2[k] then
result[k] = options2[k]
else
result[k] = v
result.bydefault[k] = true
end
end
end
return result
end
local ampm_options = {
-- lhs = input text accepted as an am/pm option
-- rhs = code used internally
['am'] = 'am',
['AM'] = 'AM',
['a.m.'] = 'a.m.',
['A.M.'] = 'A.M.',
['pm'] = 'am', -- same as am
['PM'] = 'AM',
['p.m.'] = 'a.m.',
['P.M.'] = 'A.M.',
}
local era_text = {
-- Text for displaying an era with a positive year (after adjusting
-- by replacing year with 1 - year if date.year <= 0).
-- options.era = { year<=0 , year>0 }
['BCMINUS'] = { 'BC' , '' , isbc = true, sign = MINUS },
['BCNEGATIVE'] = { 'BC' , '' , isbc = true, sign = '-' },
['BC'] = { 'BC' , '' , isbc = true },
['B.C.'] = { 'B.C.' , '' , isbc = true },
['BCE'] = { 'BCE' , '' , isbc = true },
['B.C.E.'] = { 'B.C.E.', '' , isbc = true },
['AD'] = { 'BC' , 'AD' },
['A.D.'] = { 'B.C.' , 'A.D.' },
['CE'] = { 'BCE' , 'CE' },
['C.E.'] = { 'B.C.E.', 'C.E.' },
}
local function get_era_for_year(era, year)
return (era_text[era] or era_text['BC'])[year > 0 and 2 or 1] or ''
end
local function strftime(date, format, options)
-- Return date formatted as a string using codes similar to those
-- in the C strftime library function.
local sformat = string.format
local shortcuts = {
['%c'] = '%-I:%M %p %-d %B %-Y %{era}', -- date and time: 2:30 pm 1 April 2016
['%x'] = '%-d %B %-Y %{era}', -- date: 1 April 2016
['%X'] = '%-I:%M %p', -- time: 2:30 pm
}
if shortcuts[format] then
format = shortcuts[format]
end
local codes = {
a = { field = 'dayabbr' },
A = { field = 'dayname' },
b = { field = 'monthabbr' },
B = { field = 'monthname' },
u = { fmt = '%d' , field = 'dowiso' },
w = { fmt = '%d' , field = 'dow' },
d = { fmt = '%02d', fmt2 = '%d', field = 'day' },
m = { fmt = '%02d', fmt2 = '%d', field = 'month' },
Y = { fmt = '%04d', fmt2 = '%d', field = 'year' },
H = { fmt = '%02d', fmt2 = '%d', field = 'hour' },
M = { fmt = '%02d', fmt2 = '%d', field = 'minute' },
S = { fmt = '%02d', fmt2 = '%d', field = 'second' },
j = { fmt = '%03d', fmt2 = '%d', field = 'dayofyear' },
I = { fmt = '%02d', fmt2 = '%d', field = 'hour', special = 'hour12' },
p = { field = 'hour', special = 'am' },
}
options = make_option_table(options, date.options)
local amopt = options.am
local eraopt = options.era
local function replace_code(spaces, modifier, id)
local code = codes[id]
if code then
local fmt = code.fmt
if modifier == '-' and code.fmt2 then
fmt = code.fmt2
end
local value = date[code.field]
if not value then
return nil -- an undefined field in a partial date
end
local special = code.special
if special then
if special == 'hour12' then
value = value % 12
value = value == 0 and 12 or value
elseif special == 'am' then
local ap = ({
['a.m.'] = { 'a.m.', 'p.m.' },
['AM'] = { 'AM', 'PM' },
['A.M.'] = { 'A.M.', 'P.M.' },
})[ampm_options[amopt]] or { 'am', 'pm' }
return (spaces == '' and '' or ' ') .. (value < 12 and ap[1] or ap[2])
end
end
if code.field == 'year' then
local sign = (era_text[eraopt] or {}).sign
if not sign or format:find('%{era}', 1, true) then
sign = ''
if value <= 0 then
value = 1 - value
end
else
if value >= 0 then
sign = ''
else
value = -value
end
end
return spaces .. sign .. sformat(fmt, value)
end
return spaces .. (fmt and sformat(fmt, value) or value)
end
end
local function replace_property(spaces, id)
if id == 'era' then
-- Special case so can use local era option.
local result = get_era_for_year(eraopt, date.year)
if result == '' then
return ''
end
return (spaces == '' and '' or ' ') .. result
end
local result = date[id]
if type(result) == 'string' then
return spaces .. result
end
if type(result) == 'number' then
return spaces .. tostring(result)
end
if type(result) == 'boolean' then
return spaces .. (result and '1' or '0')
end
-- This occurs if id is an undefined field in a partial date, or is the name of a function.
return nil
end
local PERCENT = '\127PERCENT\127'
return (format
:gsub('%%%%', PERCENT)
:gsub('(%s*)%%{(%w+)}', replace_property)
:gsub('(%s*)%%(%-?)(%a)', replace_code)
:gsub(PERCENT, '%%')
)
end
local function _date_text(date, fmt, options)
-- Return a formatted string representing the given date.
if not is_date(date) then
error('date:text: need a date (use "date:text()" with a colon)', 2)
end
if type(fmt) == 'string' and fmt:match('%S') then
if fmt:find('%', 1, true) then
return strftime(date, fmt, options)
end
elseif date.partial then
fmt = date.month and 'my' or 'y'
else
fmt = 'dmy'
if date.hastime then
fmt = (date.second > 0 and 'hms ' or 'hm ') .. fmt
end
end
local function bad_format()
-- For consistency with other format processing, return given format
-- (or cleaned format if original was not a string) if invalid.
return mw.text.nowiki(fmt)
end
if date.partial then
-- Ignore days in standard formats like 'ymd'.
if fmt == 'ym' or fmt == 'ymd' then
fmt = date.month and '%Y-%m %{era}' or '%Y %{era}'
elseif fmt == 'my' or fmt == 'dmy' or fmt == 'mdy' then
fmt = date.month and '%B %-Y %{era}' or '%-Y %{era}'
elseif fmt == 'y' then
fmt = date.month and '%-Y %{era}' or '%-Y %{era}'
else
return bad_format()
end
return strftime(date, fmt, options)
end
local function hm_fmt()
local plain = make_option_table(options, date.options).bydefault.am
return plain and '%H:%M' or '%-I:%M %p'
end
local need_time = date.hastime
local t = collection()
for item in fmt:gmatch('%S+') do
local f
if item == 'hm' then
f = hm_fmt()
need_time = false
elseif item == 'hms' then
f = '%H:%M:%S'
need_time = false
elseif item == 'ymd' then
f = '%Y-%m-%d %{era}'
elseif item == 'mdy' then
f = '%B %-d, %-Y %{era}'
elseif item == 'dmy' then
f = '%-d %B %-Y %{era}'
else
return bad_format()
end
t:add(f)
end
fmt = t:join(' ')
if need_time then
fmt = hm_fmt() .. ' ' .. fmt
end
return strftime(date, fmt, options)
end
local day_info = {
-- 0=Sun to 6=Sat
[0] = { 'Sun', 'Sunday' },
{ 'Mon', 'Monday' },
{ 'Tue', 'Tuesday' },
{ 'Wed', 'Wednesday' },
{ 'Thu', 'Thursday' },
{ 'Fri', 'Friday' },
{ 'Sat', 'Saturday' },
}
local month_info = {
-- 1=Jan to 12=Dec
{ 'Jan', 'January' },
{ 'Feb', 'February' },
{ 'Mar', 'March' },
{ 'Apr', 'April' },
{ 'May', 'May' },
{ 'Jun', 'June' },
{ 'Jul', 'July' },
{ 'Aug', 'August' },
{ 'Sep', 'September' },
{ 'Oct', 'October' },
{ 'Nov', 'November' },
{ 'Dec', 'December' },
}
local function name_to_number(text, translate)
if type(text) == 'string' then
return translate[text:lower()]
end
end
local function day_number(text)
return name_to_number(text, {
sun = 0, sunday = 0,
mon = 1, monday = 1,
tue = 2, tuesday = 2,
wed = 3, wednesday = 3,
thu = 4, thursday = 4,
fri = 5, friday = 5,
sat = 6, saturday = 6,
})
end
local function month_number(text)
return name_to_number(text, {
jan = 1, january = 1,
feb = 2, february = 2,
mar = 3, march = 3,
apr = 4, april = 4,
may = 5,
jun = 6, june = 6,
jul = 7, july = 7,
aug = 8, august = 8,
sep = 9, september = 9, sept = 9,
oct = 10, october = 10,
nov = 11, november = 11,
dec = 12, december = 12,
})
end
local function _list_text(list, fmt)
-- Return a list of formatted strings from a list of dates.
if not type(list) == 'table' then
error('date:list:text: need "list:text()" with a colon', 2)
end
local result = { join = _list_join }
for i, date in ipairs(list) do
result[i] = date:text(fmt)
end
return result
end
local function _date_list(date, spec)
-- Return a possibly empty numbered table of dates meeting the specification.
-- Dates in the list are in ascending order (oldest date first).
-- The spec should be a string of form "<count> <day> <op>"
-- where each item is optional and
-- count = number of items wanted in list
-- day = abbreviation or name such as Mon or Monday
-- op = >, >=, <, <= (default is > meaning after date)
-- If no count is given, the list is for the specified days in date's month.
-- The default day is date's day.
-- The spec can also be a positive or negative number:
-- -5 is equivalent to '5 <'
-- 5 is equivalent to '5' which is '5 >'
if not is_date(date) then
error('date:list: need a date (use "date:list()" with a colon)', 2)
end
local list = { text = _list_text }
if date.partial then
return list
end
local count, offset, operation
local ops = {
['>='] = { before = false, include = true },
['>'] = { before = false, include = false },
['<='] = { before = true , include = true },
['<'] = { before = true , include = false },
}
if spec then
if type(spec) == 'number' then
count = floor(spec + 0.5)
if count < 0 then
count = -count
operation = ops['<']
end
elseif type(spec) == 'string' then
local num, day, op = spec:match('^%s*(%d*)%s*(%a*)%s*([<>=]*)%s*$')
if not num then
return list
end
if num ~= '' then
count = tonumber(num)
end
if day ~= '' then
local dow = day_number(day:gsub('[sS]$', '')) -- accept plural days
if not dow then
return list
end
offset = dow - date.dow
end
operation = ops[op]
else
return list
end
end
offset = offset or 0
operation = operation or ops['>']
local datefrom, dayfirst, daylast
if operation.before then
if offset > 0 or (offset == 0 and not operation.include) then
offset = offset - 7
end
if count then
if count > 1 then
offset = offset - 7*(count - 1)
end
datefrom = date + offset
else
daylast = date.day + offset
dayfirst = daylast % 7
if dayfirst == 0 then
dayfirst = 7
end
end
else
if offset < 0 or (offset == 0 and not operation.include) then
offset = offset + 7
end
if count then
datefrom = date + offset
else
dayfirst = date.day + offset
daylast = date.monthdays
end
end
if not count then
if daylast < dayfirst then
return list
end
count = floor((daylast - dayfirst)/7) + 1
datefrom = Date(date, {day = dayfirst})
end
for i = 1, count do
if not datefrom then break end -- exceeds date limits
list[i] = datefrom
datefrom = datefrom + 7
end
return list
end
-- A table to get the current date/time (UTC), but only if needed.
local current = setmetatable({}, {
__index = function (self, key)
local d = os.date('!*t')
self.year = d.year
self.month = d.month
self.day = d.day
self.hour = d.hour
self.minute = d.min
self.second = d.sec
return rawget(self, key)
end })
local function extract_date(newdate, text)
-- Parse the date/time in text and return n, o where
-- n = table of numbers with date/time fields
-- o = table of options for AM/PM or AD/BC or format, if any
-- or return nothing if date is known to be invalid.
-- Caller determines if the values in n are valid.
-- A year must be positive ('1' to '9999'); use 'BC' for BC.
-- In a y-m-d string, the year must be four digits to avoid ambiguity
-- ('0001' to '9999'). The only way to enter year <= 0 is by specifying
-- the date as three numeric parameters like ymd Date(-1, 1, 1).
-- Dates of form d/m/y, m/d/y, y/m/d are rejected as potentially ambiguous.
local date, options = {}, {}
if text:sub(-1) == 'Z' then
-- Extract date/time from a Wikidata timestamp.
-- The year can be 1 to 16 digits but this module handles 1 to 4 digits only.
-- Examples: '+2016-06-21T14:30:00Z', '-0000000180-00-00T00:00:00Z'.
local sign, y, m, d, H, M, S = text:match('^([+%-])(%d+)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)Z$')
if sign then
y = tonumber(y)
if sign == '-' and y > 0 then
y = -y
end
if y <= 0 then
options.era = 'BCE'
end
date.year = y
m = tonumber(m)
d = tonumber(d)
H = tonumber(H)
M = tonumber(M)
S = tonumber(S)
if m == 0 then
newdate.partial = true
return date, options
end
date.month = m
if d == 0 then
newdate.partial = true
return date, options
end
date.day = d
if H > 0 or M > 0 or S > 0 then
date.hour = H
date.minute = M
date.second = S
end
return date, options
end
return
end
local function extract_ymd(item)
-- Called when no day or month has been set.
local y, m, d = item:match('^(%d%d%d%d)%-(%w+)%-(%d%d?)$')
if y then
if date.year then
return
end
if m:match('^%d%d?$') then
m = tonumber(m)
else
m = month_number(m)
end
if m then
date.year = tonumber(y)
date.month = m
date.day = tonumber(d)
return true
end
end
end
local function extract_day_or_year(item)
-- Called when a day would be valid, or
-- when a year would be valid if no year has been set and partial is set.
local number, suffix = item:match('^(%d%d?%d?%d?)(.*)$')
if number then
local n = tonumber(number)
if #number <= 2 and n <= 31 then
suffix = suffix:lower()
if suffix == '' or suffix == 'st' or suffix == 'nd' or suffix == 'rd' or suffix == 'th' then
date.day = n
return true
end
elseif suffix == '' and newdate.partial and not date.year then
date.year = n
return true
end
end
end
local function extract_month(item)
-- A month must be given as a name or abbreviation; a number could be ambiguous.
local m = month_number(item)
if m then
date.month = m
return true
end
end
local function extract_time(item)
local h, m, s = item:match('^(%d%d?):(%d%d)(:?%d*)$')
if date.hour or not h then
return
end
if s ~= '' then
s = s:match('^:(%d%d)$')
if not s then
return
end
end
date.hour = tonumber(h)
date.minute = tonumber(m)
date.second = tonumber(s) -- nil if empty string
return true
end
local item_count = 0
local index_time
local function set_ampm(item)
local H = date.hour
if H and not options.am and index_time + 1 == item_count then
options.am = ampm_options[item] -- caller checked this is not nil
if item:match('^[Aa]') then
if not (1 <= H and H <= 12) then
return
end
if H == 12 then
date.hour = 0
end
else
if not (1 <= H and H <= 23) then
return
end
if H <= 11 then
date.hour = H + 12
end
end
return true
end
end
for item in text:gsub(',', ' '):gsub(' ', ' '):gmatch('%S+') do
item_count = item_count + 1
if era_text[item] then
-- Era is accepted in peculiar places.
if options.era then
return
end
options.era = item
elseif ampm_options[item] then
if not set_ampm(item) then
return
end
elseif item:find(':', 1, true) then
if not extract_time(item) then
return
end
index_time = item_count
elseif date.day and date.month then
if date.year then
return -- should be nothing more so item is invalid
end
if not item:match('^(%d%d?%d?%d?)$') then
return
end
date.year = tonumber(item)
elseif date.day then
if not extract_month(item) then
return
end
elseif date.month then
if not extract_day_or_year(item) then
return
end
elseif extract_month(item) then
options.format = 'mdy'
elseif extract_ymd(item) then
options.format = 'ymd'
elseif extract_day_or_year(item) then
if date.day then
options.format = 'dmy'
end
else
return
end
end
if not date.year or date.year == 0 then
return
end
local era = era_text[options.era]
if era and era.isbc then
date.year = 1 - date.year
end
return date, options
end
local function autofill(date1, date2)
-- Fill any missing month or day in each date using the
-- corresponding component from the other date, if present,
-- or with 1 if both dates are missing the month or day.
-- This gives a good result for calculating the difference
-- between two partial dates when no range is wanted.
-- Return filled date1, date2 (two full dates).
local function filled(a, b)
local fillmonth, fillday
if not a.month then
fillmonth = b.month or 1
end
if not a.day then
fillday = b.day or 1
end
if fillmonth or fillday then -- need to create a new date
a = Date(a, { month = fillmonth, day = fillday })
end
return a
end
return filled(date1, date2), filled(date2, date1)
end
local function date_add_sub(lhs, rhs, is_sub)
-- Return a new date from calculating (lhs + rhs) or (lhs - rhs),
-- or return nothing if invalid.
-- The result is nil if the calculated date exceeds allowable limits.
-- Caller ensures that lhs is a date; its properties are copied for the new date.
if lhs.partial then
-- Adding to a partial is not supported.
-- Can subtract a date or partial from a partial, but this is not called for that.
return
end
local function is_prefix(text, word, minlen)
local n = #text
return (minlen or 1) <= n and n <= #word and text == word:sub(1, n)
end
local function do_days(n)
local forcetime, jd
if floor(n) == n then
jd = lhs.jd
else
forcetime = not lhs.hastime
jd = lhs.jdz
end
jd = jd + (is_sub and -n or n)
if forcetime then
jd = tostring(jd)
if not jd:find('.', 1, true) then
jd = jd .. '.0'
end
end
return Date(lhs, 'juliandate', jd)
end
if type(rhs) == 'number' then
-- Add/subtract days, including fractional days.
return do_days(rhs)
end
if type(rhs) == 'string' then
-- rhs is a single component like '26m' or '26 months' (with optional sign).
-- Fractions like '3.25d' are accepted for the units which are handled as days.
local sign, numstr, id = rhs:match('^%s*([+-]?)([%d%.]+)%s*(%a+)$')
if sign then
if sign == '-' then
is_sub = not (is_sub and true or false)
end
local y, m, days
local num = tonumber(numstr)
if not num then
return
end
id = id:lower()
if is_prefix(id, 'years') then
y = num
m = 0
elseif is_prefix(id, 'months') then
y = floor(num / 12)
m = num % 12
elseif is_prefix(id, 'weeks') then
days = num * 7
elseif is_prefix(id, 'days') then
days = num
elseif is_prefix(id, 'hours') then
days = num / 24
elseif is_prefix(id, 'minutes', 3) then
days = num / (24 * 60)
elseif is_prefix(id, 'seconds') then
days = num / (24 * 3600)
else
return
end
if days then
return do_days(days)
end
if numstr:find('.', 1, true) then
return
end
if is_sub then
y = -y
m = -m
end
assert(-11 <= m and m <= 11)
y = lhs.year + y
m = lhs.month + m
if m > 12 then
y = y + 1
m = m - 12
elseif m < 1 then
y = y - 1
m = m + 12
end
local d = math.min(lhs.day, days_in_month(y, m, lhs.calendar))
return Date(lhs, y, m, d)
end
end
if is_diff(rhs) then
local days = rhs.age_days
if (is_sub or false) ~= (rhs.isnegative or false) then
days = -days
end
return lhs + days
end
end
local full_date_only = {
dayabbr = true,
dayname = true,
dow = true,
dayofweek = true,
dowiso = true,
dayofweekiso = true,
dayofyear = true,
gsd = true,
juliandate = true,
jd = true,
jdz = true,
jdnoon = true,
}
-- Metatable for a date's calculated fields.
local datemt = {
__index = function (self, key)
if rawget(self, 'partial') then
if full_date_only[key] then return end
if key == 'monthabbr' or key == 'monthdays' or key == 'monthname' then
if not self.month then return end
end
end
local value
if key == 'dayabbr' then
value = day_info[self.dow][1]
elseif key == 'dayname' then
value = day_info[self.dow][2]
elseif key == 'dow' then
value = (self.jdnoon + 1) % 7 -- day-of-week 0=Sun to 6=Sat
elseif key == 'dayofweek' then
value = self.dow
elseif key == 'dowiso' then
value = (self.jdnoon % 7) + 1 -- ISO day-of-week 1=Mon to 7=Sun
elseif key == 'dayofweekiso' then
value = self.dowiso
elseif key == 'dayofyear' then
local first = Date(self.year, 1, 1, self.calendar).jdnoon
value = self.jdnoon - first + 1 -- day-of-year 1 to 366
elseif key == 'era' then
-- Era text (never a negative sign) from year and options.
value = get_era_for_year(self.options.era, self.year)
elseif key == 'format' then
value = self.options.format or 'dmy'
elseif key == 'gsd' then
-- GSD = 1 from 00:00:00 to 23:59:59 on 1 January 1 AD Gregorian calendar,
-- which is from jd 1721425.5 to 1721426.49999.
value = floor(self.jd - 1721424.5)
elseif key == 'juliandate' or key == 'jd' or key == 'jdz' then
local jd, jdz = julian_date(self)
rawset(self, 'juliandate', jd)
rawset(self, 'jd', jd)
rawset(self, 'jdz', jdz)
return key == 'jdz' and jdz or jd
elseif key == 'jdnoon' then
-- Julian date at noon (an integer) on the calendar day when jd occurs.
value = floor(self.jd + 0.5)
elseif key == 'isleapyear' then
value = is_leap_year(self.year, self.calendar)
elseif key == 'monthabbr' then
value = month_info[self.month][1]
elseif key == 'monthdays' then
value = days_in_month(self.year, self.month, self.calendar)
elseif key == 'monthname' then
value = month_info[self.month][2]
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
-- Date operators.
local function mt_date_add(lhs, rhs)
if not is_date(lhs) then
lhs, rhs = rhs, lhs -- put date on left (it must be a date for this to have been called)
end
return date_add_sub(lhs, rhs)
end
local function mt_date_sub(lhs, rhs)
if is_date(lhs) then
if is_date(rhs) then
return DateDiff(lhs, rhs)
end
return date_add_sub(lhs, rhs, true)
end
end
local function mt_date_concat(lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end
local function mt_date_tostring(self)
return self:text()
end
local function mt_date_eq(lhs, rhs)
-- Return true if dates identify same date/time where, for example,
-- Date(-4712, 1, 1, 'Julian') == Date(-4713, 11, 24, 'Gregorian') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
-- The months may both be nil, but must be the same.
return lhs.year == rhs.year and lhs.month == rhs.month and lhs.calendar == rhs.calendar
end
return lhs.jdz == rhs.jdz
end
local function mt_date_lt(lhs, rhs)
-- Return true if lhs < rhs, for example,
-- Date('1 Jan 2016') < Date('06:00 1 Jan 2016') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
if lhs.calendar ~= rhs.calendar then
return lhs.calendar == 'Julian'
end
if lhs.partial then
lhs = lhs.partial.first
end
if rhs.partial then
rhs = rhs.partial.first
end
end
return lhs.jdz < rhs.jdz
end
--[[ Examples of syntax to construct a date:
Date(y, m, d, 'julian') default calendar is 'gregorian'
Date(y, m, d, H, M, S, 'julian')
Date('juliandate', jd, 'julian') if jd contains "." text output includes H:M:S
Date('currentdate')
Date('currentdatetime')
Date('1 April 1995', 'julian') parse date from text
Date('1 April 1995 AD', 'julian') using an era sets a flag to do the same for output
Date('04:30:59 1 April 1995', 'julian')
Date(date) copy of an existing date
Date(date, t) same, updated with y,m,d,H,M,S fields from table t
Date(t) date with y,m,d,H,M,S fields from table t
]]
function Date(...) -- for forward declaration above
-- Return a table holding a date assuming a uniform calendar always applies
-- (proleptic Gregorian calendar or proleptic Julian calendar), or
-- return nothing if date is invalid.
-- A partial date has a valid year, however its month may be nil, and
-- its day and time fields are nil.
-- Field partial is set to false (if a full date) or a table (if a partial date).
local calendars = { julian = 'Julian', gregorian = 'Gregorian' }
local newdate = {
_id = uniq,
calendar = 'Gregorian', -- default is Gregorian calendar
hastime = false, -- true if input sets a time
hour = 0, -- always set hour/minute/second so don't have to handle nil
minute = 0,
second = 0,
options = {},
list = _date_list,
subtract = function (self, rhs, options)
return DateDiff(self, rhs, options)
end,
text = _date_text,
}
local argtype, datetext, is_copy, jd_number, tnums
local numindex = 0
local numfields = { 'year', 'month', 'day', 'hour', 'minute', 'second' }
local numbers = {}
for _, v in ipairs({...}) do
v = strip_to_nil(v)
local vlower = type(v) == 'string' and v:lower() or nil
if v == nil then
-- Ignore empty arguments after stripping so modules can directly pass template parameters.
elseif calendars[vlower] then
newdate.calendar = calendars[vlower]
elseif vlower == 'partial' then
newdate.partial = true
elseif vlower == 'fix' then
newdate.want_fix = true
elseif is_date(v) then
-- Copy existing date (items can be overridden by other arguments).
if is_copy or tnums then
return
end
is_copy = true
newdate.calendar = v.calendar
newdate.partial = v.partial
newdate.hastime = v.hastime
newdate.options = v.options
newdate.year = v.year
newdate.month = v.month
newdate.day = v.day
newdate.hour = v.hour
newdate.minute = v.minute
newdate.second = v.second
elseif type(v) == 'table' then
if tnums then
return
end
tnums = {}
local tfields = { year=1, month=1, day=1, hour=2, minute=2, second=2 }
for tk, tv in pairs(v) do
if tfields[tk] then
tnums[tk] = tonumber(tv)
end
if tfields[tk] == 2 then
newdate.hastime = true
end
end
else
local num = tonumber(v)
if not num and argtype == 'setdate' and numindex == 1 then
num = month_number(v)
end
if num then
if not argtype then
argtype = 'setdate'
end
if argtype == 'setdate' and numindex < 6 then
numindex = numindex + 1
numbers[numfields[numindex]] = num
elseif argtype == 'juliandate' and not jd_number then
jd_number = num
if type(v) == 'string' then
if v:find('.', 1, true) then
newdate.hastime = true
end
elseif num ~= floor(num) then
-- The given value was a number. The time will be used
-- if the fractional part is nonzero.
newdate.hastime = true
end
else
return
end
elseif argtype then
return
elseif type(v) == 'string' then
if v == 'currentdate' or v == 'currentdatetime' or v == 'juliandate' then
argtype = v
else
argtype = 'datetext'
datetext = v
end
else
return
end
end
end
if argtype == 'datetext' then
if tnums or not set_date_from_numbers(newdate, extract_date(newdate, datetext)) then
return
end
elseif argtype == 'juliandate' then
newdate.partial = nil
newdate.jd = jd_number
if not set_date_from_jd(newdate) then
return
end
elseif argtype == 'currentdate' or argtype == 'currentdatetime' then
newdate.partial = nil
newdate.year = current.year
newdate.month = current.month
newdate.day = current.day
if argtype == 'currentdatetime' then
newdate.hour = current.hour
newdate.minute = current.minute
newdate.second = current.second
newdate.hastime = true
end
newdate.calendar = 'Gregorian' -- ignore any given calendar name
elseif argtype == 'setdate' then
if tnums or not set_date_from_numbers(newdate, numbers) then
return
end
elseif not (is_copy or tnums) then
return
end
if tnums then
newdate.jd = nil -- force recalculation in case jd was set before changes from tnums
if not set_date_from_numbers(newdate, tnums) then
return
end
end
if newdate.partial then
local year = newdate.year
local month = newdate.month
local first = Date(year, month or 1, 1, newdate.calendar)
month = month or 12
local last = Date(year, month, days_in_month(year, month), newdate.calendar)
newdate.partial = { first = first, last = last }
else
newdate.partial = false -- avoid index lookup
end
setmetatable(newdate, datemt)
local readonly = {}
local mt = {
__index = newdate,
__newindex = function(t, k, v) error('date.' .. tostring(k) .. ' is read-only', 2) end,
__add = mt_date_add,
__sub = mt_date_sub,
__concat = mt_date_concat,
__tostring = mt_date_tostring,
__eq = mt_date_eq,
__lt = mt_date_lt,
}
return setmetatable(readonly, mt)
end
local function _diff_age(diff, code, options)
-- Return a tuple of integer values from diff as specified by code, except that
-- each integer may be a list of two integers for a diff with a partial date, or
-- return nil if the code is not supported.
-- If want round, the least significant unit is rounded to nearest whole unit.
-- For a duration, an extra day is added.
local wantround, wantduration, wantrange
if type(options) == 'table' then
wantround = options.round
wantduration = options.duration
wantrange = options.range
else
wantround = options
end
if not is_diff(diff) then
local f = wantduration and 'duration' or 'age'
error(f .. ': need a date difference (use "diff:' .. f .. '()" with a colon)', 2)
end
if diff.partial then
-- Ignore wantround, wantduration.
local function choose(v)
if type(v) == 'table' then
if not wantrange or v[1] == v[2] then
-- Example: Date('partial', 2005) - Date('partial', 2001) gives
-- diff.years = { 3, 4 } to show the range of possible results.
-- If do not want a range, choose the second value as more expected.
return v[2]
end
end
return v
end
if code == 'ym' or code == 'ymd' then
if not wantrange and diff.iszero then
-- This avoids an unexpected result such as
-- Date('partial', 2001) - Date('partial', 2001)
-- giving diff = { years = 0, months = { 0, 11 } }
-- which would be reported as 0 years and 11 months.
return 0, 0
end
return choose(diff.partial.years), choose(diff.partial.months)
end
if code == 'y' then
return choose(diff.partial.years)
end
if code == 'm' or code == 'w' or code == 'd' then
return choose({ diff.partial.mindiff:age(code), diff.partial.maxdiff:age(code) })
end
return nil
end
local extra_days = wantduration and 1 or 0
if code == 'wd' or code == 'w' or code == 'd' then
local offset = wantround and 0.5 or 0
local days = diff.age_days + extra_days
if code == 'wd' or code == 'd' then
days = floor(days + offset)
if code == 'd' then
return days
end
return floor(days/7), days % 7
end
return floor(days/7 + offset)
end
local H, M, S = diff.hours, diff.minutes, diff.seconds
if code == 'dh' or code == 'dhm' or code == 'dhms' or code == 'h' or code == 'hm' or code == 'hms' then
local days = floor(diff.age_days + extra_days)
local inc_hour
if wantround then
if code == 'dh' or code == 'h' then
if M >= 30 then
inc_hour = true
end
elseif code == 'dhm' or code == 'hm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
else
-- Nothing needed because S is an integer.
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
days = days + 1
end
end
end
if code == 'dh' or code == 'dhm' or code == 'dhms' then
if code == 'dh' then
return days, H
elseif code == 'dhm' then
return days, H, M
else
return days, H, M, S
end
end
local hours = days * 24 + H
if code == 'h' then
return hours
elseif code == 'hm' then
return hours, M
end
return hours, M, S
end
if wantround then
local inc_hour
if code == 'ymdh' or code == 'ymwdh' then
if M >= 30 then
inc_hour = true
end
elseif code == 'ymdhm' or code == 'ymwdhm' then
if S >= 30 then
M = M + 1
if M >= 60 then
M = 0
inc_hour = true
end
end
elseif code == 'ymd' or code == 'ymwd' or code == 'yd' or code == 'md' then
if H >= 12 then
extra_days = extra_days + 1
end
end
if inc_hour then
H = H + 1
if H >= 24 then
H = 0
extra_days = extra_days + 1
end
end
end
local y, m, d = diff.years, diff.months, diff.days
if extra_days > 0 then
d = d + extra_days
if d > 28 or code == 'yd' then
-- Recalculate in case have passed a month.
diff = diff.date1 + extra_days - diff.date2
y, m, d = diff.years, diff.months, diff.days
end
end
if code == 'ymd' then
return y, m, d
elseif code == 'yd' then
if y > 0 then
-- It is known that diff.date1 > diff.date2.
diff = diff.date1 - (diff.date2 + (y .. 'y'))
end
return y, floor(diff.age_days)
elseif code == 'md' then
return y * 12 + m, d
elseif code == 'ym' or code == 'm' then
if wantround then
if d >= 16 then
m = m + 1
if m >= 12 then
m = 0
y = y + 1
end
end
end
if code == 'ym' then
return y, m
end
return y * 12 + m
elseif code == 'ymw' then
local weeks = floor(d/7)
if wantround then
local days = d % 7
if days > 3 or (days == 3 and H >= 12) then
weeks = weeks + 1
end
end
return y, m, weeks
elseif code == 'ymwd' then
return y, m, floor(d/7), d % 7
elseif code == 'ymdh' then
return y, m, d, H
elseif code == 'ymwdh' then
return y, m, floor(d/7), d % 7, H
elseif code == 'ymdhm' then
return y, m, d, H, M
elseif code == 'ymwdhm' then
return y, m, floor(d/7), d % 7, H, M
end
if code == 'y' then
if wantround and m >= 6 then
y = y + 1
end
return y
end
return nil
end
local function _diff_duration(diff, code, options)
if type(options) ~= 'table' then
options = { round = options }
end
options.duration = true
return _diff_age(diff, code, options)
end
-- Metatable for some operations on date differences.
diffmt = { -- for forward declaration above
__concat = function (lhs, rhs)
return tostring(lhs) .. tostring(rhs)
end,
__tostring = function (self)
return tostring(self.age_days)
end,
__index = function (self, key)
local value
if key == 'age_days' then
if rawget(self, 'partial') then
local function jdz(date)
return (date.partial and date.partial.first or date).jdz
end
value = jdz(self.date1) - jdz(self.date2)
else
value = self.date1.jdz - self.date2.jdz
end
end
if value ~= nil then
rawset(self, key, value)
return value
end
end,
}
function DateDiff(date1, date2, options) -- for forward declaration above
-- Return a table with the difference between two dates (date1 - date2).
-- The difference is negative if date1 is older than date2.
-- Return nothing if invalid.
-- If d = date1 - date2 then
-- date1 = date2 + d
-- If date1 >= date2 and the dates have no H:M:S time specified then
-- date1 = date2 + (d.years..'y') + (d.months..'m') + d.days
-- where the larger time units are added first.
-- The result of Date(2015,1,x) + '1m' is Date(2015,2,28) for
-- x = 28, 29, 30, 31. That means, for example,
-- d = Date(2015,3,3) - Date(2015,1,31)
-- gives d.years, d.months, d.days = 0, 1, 3 (excluding date1).
if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then
return
end
local wantfill
if type(options) == 'table' then
wantfill = options.fill
end
local isnegative = false
local iszero = false
if date1 < date2 then
isnegative = true
date1, date2 = date2, date1
elseif date1 == date2 then
iszero = true
end
-- It is known that date1 >= date2 (period is from date2 to date1).
if date1.partial or date2.partial then
-- Two partial dates might have timelines:
---------------------A=================B--- date1 is from A to B inclusive
--------C=======D-------------------------- date2 is from C to D inclusive
-- date1 > date2 iff A > C (date1.partial.first > date2.partial.first)
-- The periods can overlap ('April 2001' - '2001'):
-------------A===B------------------------- A=2001-04-01 B=2001-04-30
--------C=====================D------------ C=2001-01-01 D=2001-12-31
if wantfill then
date1, date2 = autofill(date1, date2)
else
local function zdiff(date1, date2)
local diff = date1 - date2
if diff.isnegative then
return date1 - date1 -- a valid diff in case we call its methods
end
return diff
end
local function getdate(date, which)
return date.partial and date.partial[which] or date
end
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
local years, months
if maxdiff.years == mindiff.years then
years = maxdiff.years
if maxdiff.months == mindiff.months then
months = maxdiff.months
else
months = { mindiff.months, maxdiff.months }
end
else
years = { mindiff.years, maxdiff.years }
end
return setmetatable({
date1 = date1,
date2 = date2,
partial = {
years = years,
months = months,
maxdiff = maxdiff,
mindiff = mindiff,
},
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
end
local y1, m1 = date1.year, date1.month
local y2, m2 = date2.year, date2.month
local years = y1 - y2
local months = m1 - m2
local d1 = date1.day + hms(date1)
local d2 = date2.day + hms(date2)
local days, time
if d1 >= d2 then
days = d1 - d2
else
months = months - 1
-- Get days in previous month (before the "to" date) given December has 31 days.
local dpm = m1 > 1 and days_in_month(y1, m1 - 1, date1.calendar) or 31
if d2 >= dpm then
days = d1 - hms(date2)
else
days = dpm - d2 + d1
end
end
if months < 0 then
years = years - 1
months = months + 12
end
days, time = math.modf(days)
local H, M, S = h_m_s(time)
return setmetatable({
date1 = date1,
date2 = date2,
partial = false, -- avoid index lookup
years = years,
months = months,
days = days,
hours = H,
minutes = M,
seconds = S,
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
return {
_current = current,
_Date = Date,
_days_in_month = days_in_month,
}
ba95c5be544bbca7b661a5038c292cb5ef61de6d
Template:Resize
10
229
478
477
2024-08-04T12:41:29Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{2|}}}
|<span style="font-size:{{{1|}}};">{{{2|}}}</span>
|<span style="font-size:90%;">{{{1}}}</span>
}}<noinclude>
{{doc}}
<!--PLEASE ADD CATEGORIES AND INTERWIKIS TO THE /doc SUBPAGE, THANKS-->
</noinclude>
c7461944f74c760bc5b2d94c8b7c42c6c024459c
Template:MONTHNAME
10
230
480
479
2024-08-04T12:41:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#if:{{{1|}}}|{{#switch:{{MONTHNUMBER|{{{1}}}}}|1=1月|2=2月|3=3月|4=4月|5=5月|6=6月|7=7月|8=8月|9=9月|10=10月|11=11月|12=12月|Incorrect required parameter 1=''month''!}}|Missing required parameter 1=''month''!}}</includeonly><noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
1589efdb31d554291283e4aa24741ab640a30ef0
Template:MONTHNUMBER
10
231
482
481
2024-08-04T12:41:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{1|}}}|{{#switch:{{lc:{{{1}}}}}|january|一月|jan=1|february|二月|feb=2|march|三月|mar=3|apr|四月|april=4|五月|may=5|june|六月|jun=6|july|七月|jul=7|august|八月|aug=8|september|九月|sep=9|october|十月|oct=10|november|十一月|nov=11|december|十二月|dec=12|{{#ifexpr:{{{1}}}<0|{{#ifexpr:(({{{1}}})round 0)!=({{{1}}})|{{#expr:12-(((0.5-({{{1}}}))round 0)mod 12)}}|{{#expr:12-(((11.5-({{{1}}}))round 0)mod 12)}}}}|{{#expr:(((10.5+{{{1}}})round 0)mod 12)+1}}}}}}|Missing required parameter 1=''month''!}}<noinclude>{{doc}}</noinclude>
23dfd4382f37871a866bf3d27ff8140ea7b481ee
Template:Birth date
10
232
484
483
2024-08-04T12:41:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span style="display:none">(<span class="bday">{{{1|{{{year}}}}}}-{{padleft:{{MONTHNUMBER|{{{2|{{{month}}}}}}}}|2|0}}-{{padleft:{{{3|{{{day}}}}}}|2|0}}</span>)</span>{{#expr:{{{1|{{{year<noinclude>|1900</noinclude>}}}}}}}}年{{#if:{{{df|}}}
|{{MONTHNAME|{{{2|{{{month}}}}}}}}{{#expr:{{{3|{{{day}}}}}}}}日
|{{MONTHNAME|{{{2|{{{month<noinclude>|1</noinclude>}}}}}}}}{{#expr:{{{3|{{{day<noinclude>|1</noinclude>}}}}}}}}日
}}<noinclude>
{{Documentation|Template:Birth date and age/doc}}
</noinclude>
f5d04281beeaddf72fa418cea3cd3faac5db8b4e
Template:Navbox with collapsible groups
10
233
486
485
2024-08-04T12:41:33Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:navbox|navbox
|name = {{{name|<noinclude>Navbox with collapsible groups</noinclude>}}}
|navbar = {{{navbar|}}}
|state = {{{state|<noinclude>uncollapsed</noinclude>}}}
|border = {{{border|{{{1|}}}}}}
|title = {{{title<includeonly>|</includeonly>}}}
|above = {{{above|}}}
|image = {{{image|}}}
|imageleft = {{{imageleft|}}}
|bodyclass = {{{bodyclass|}}}
|titleclass = {{{titleclass|}}}
|aboveclass = {{{aboveclass|}}}
|belowclass = {{{belowclass|}}}
|groupclass = {{{groupclass|}}}
|listclass = {{{listclass|}}}
|imageclass = {{{imageclass|}}}
|style = {{{style|}}}{{{bodystyle|}}}
|basestyle = {{{basestyle|}}}
|titlestyle = {{{titlestyle|}}}
|abovestyle = {{{abovestyle|}}}
|belowstyle = {{{belowstyle|}}}
|imagestyle = {{{imagestyle|}}}
|imageleftstyle = {{{imageleftstyle|}}}
|list1 =
{{#if:{{{group1<includeonly>|</includeonly>}}}{{{sect1|}}}{{{section1|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr1}}} |uncollapsed |{{{state1|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group1style|}}}{{{sect1titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list1style|}}}{{{content1style|}}}
|title = {{{group1<includeonly>|</includeonly>}}}{{{sect1|}}}{{{section1|}}}<noinclude> or {{{section1}}} or {{{sect1}}}</noinclude>
|list1 = {{{list1<includeonly>|</includeonly>}}}{{{content1|}}}<noinclude> or {{{content1}}}</noinclude>
|image = {{{image1|}}}
|imageleft = {{{imageleft1|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list1|}}}{{{content1|}}}
}}
|list2 =
{{#if:{{{group2<includeonly>|</includeonly>}}}{{{sect2|}}}{{{section2|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr2}}} |uncollapsed |{{{state2|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group2style|}}}{{{sect2titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list2style|}}}{{{content2style|}}}
|title = {{{group2<includeonly>|</includeonly>}}}{{{sect2|}}}{{{section2|}}}<noinclude> or {{{section2}}} or {{{sect2}}}</noinclude>
|list1 = {{{list2<includeonly>|</includeonly>}}}{{{content2|}}}<noinclude> or {{{content2}}}</noinclude>
|image = {{{image2|}}}
|imageleft = {{{imageleft2|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list2|}}}{{{content2|}}}
}}
|list3 =
{{#if:{{{group3<includeonly>|</includeonly>}}}{{{sect3|}}}{{{section3|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr3}}} |uncollapsed |{{{state3|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group3style|}}}{{{sect3titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list3style|}}}{{{content3style|}}}
|title = {{{group3<includeonly>|</includeonly>}}}{{{sect3|}}}{{{section3|}}}<noinclude> or {{{section3}}} or {{{sect3}}}</noinclude>
|list1 = {{{list3<includeonly>|</includeonly>}}}{{{content3|}}}<noinclude> or {{{content3}}}</noinclude>
|image = {{{image3|}}}
|imageleft = {{{imageleft3|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list3|}}}{{{content3|}}}
}}
|list4 =
{{#if:{{{group4<includeonly>|</includeonly>}}}{{{sect4|}}}{{{section4|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr4}}} |uncollapsed |{{{state4|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group4style|}}}{{{sect4titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list4style|}}}{{{content4style|}}}
|title = {{{group4<includeonly>|</includeonly>}}}{{{sect4|}}}{{{section4|}}}<noinclude> or {{{section4}}} or {{{sect4}}}</noinclude>
|list1 = {{{list4<includeonly>|</includeonly>}}}{{{content4|}}}<noinclude> or {{{content4}}}</noinclude>
|image = {{{image4|}}}
|imageleft = {{{imageleft4|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list4|}}}{{{content4|}}}
}}
|list5 =
{{#if:{{{group5<includeonly>|</includeonly>}}}{{{sect5|}}}{{{section5|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr5}}} |uncollapsed |{{{state5|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group5style|}}}{{{sect5titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list5style|}}}{{{content5style|}}}
|title = {{{group5<includeonly>|</includeonly>}}}{{{sect5|}}}{{{section5|}}}<noinclude> or {{{section5}}} or {{{sect5}}}</noinclude>
|list1 = {{{list5<includeonly>|</includeonly>}}}{{{content5|}}}<noinclude> or {{{content5}}}</noinclude>
|image = {{{image5|}}}
|imageleft = {{{imageleft5|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list5|}}}{{{content5|}}}
}}
|list6 =
{{#if:{{{group6|}}}{{{sect6|}}}{{{section6|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr6}}} |uncollapsed |{{{state6|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group6style|}}}{{{sect6titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list6style|}}}{{{content6style|}}}
|title = {{{group6|}}}{{{sect6|}}}{{{section6|}}}
|list1 = {{{list6|}}}{{{content6|}}}
|image = {{{image6|}}}
|imageleft = {{{imageleft6|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list6|}}}{{{content6|<noinclude>''(...etc, to group20/sect20/section20 and list20/content20)''</noinclude>}}}
}}
|list7 =
{{#if:{{{group7|}}}{{{sect7|}}}{{{section7|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr7}}} |uncollapsed |{{{state7|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group7style|}}}{{{sect7titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list7style|}}}{{{content7style|}}}
|title = {{{group7|}}}{{{sect7|}}}{{{section7|}}}
|list1 = {{{list7|}}}{{{content7|}}}
|image = {{{image7|}}}
|imageleft = {{{imageleft7|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list7|}}}{{{content7|}}}
}}
|list8 =
{{#if:{{{group8|}}}{{{sect8|}}}{{{section8|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr8}}} |uncollapsed |{{{state8|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group8style|}}}{{{sect8titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list8style|}}}{{{content8style|}}}
|title = {{{group8|}}}{{{sect8|}}}{{{section8|}}}
|list1 = {{{list8|}}}{{{content8|}}}
|image = {{{image8|}}}
|imageleft = {{{imageleft8|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list8|}}}{{{content8|}}}
}}
|list9 =
{{#if:{{{group9|}}}{{{sect9|}}}{{{section9|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr9}}} |uncollapsed |{{{state9|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group9style|}}}{{{sect9titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list9style|}}}{{{content9style|}}}
|title = {{{group9|}}}{{{sect9|}}}{{{section9|}}}
|list1 = {{{list9|}}}{{{content9|}}}
|image = {{{image9|}}}
|imageleft = {{{imageleft9|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list9|}}}{{{content9|}}}
}}
|list10 =
{{#if:{{{group10|}}}{{{sect10|}}}{{{section10|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr10}}} |uncollapsed |{{{state10|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group10style|}}}{{{sect10titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list10style|}}}{{{content10style|}}}
|title = {{{group10|}}}{{{sect10|}}}{{{section10|}}}
|list1 = {{{list10|}}}{{{content10|}}}
|image = {{{image10|}}}
|imageleft = {{{imageleft10|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list10|}}}{{{content10|}}}
}}
|list11 =
{{#if:{{{group11|}}}{{{sect11|}}}{{{section11|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr11}}} |uncollapsed |{{{state11|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group11style|}}}{{{sect11titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list11style|}}}{{{content11style|}}}
|title = {{{group11|}}}{{{sect11|}}}{{{section11|}}}
|list1 = {{{list11|}}}{{{content11|}}}
|image = {{{image11|}}}
|imageleft = {{{imageleft11|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list11|}}}{{{content11|}}}
}}
|list12 =
{{#if:{{{group12|}}}{{{sect12|}}}{{{section12|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr12}}} |uncollapsed |{{{state12|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group12style|}}}{{{sect12titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list12style|}}}{{{content12style|}}}
|title = {{{group12|}}}{{{sect12|}}}{{{section12|}}}
|list1 = {{{list12|}}}{{{content12|}}}
|image = {{{image12|}}}
|imageleft = {{{imageleft12|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list12|}}}{{{content12|}}}
}}
|list13 =
{{#if:{{{group13|}}}{{{sect13|}}}{{{section13|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr13}}} |uncollapsed |{{{state13|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group13style|}}}{{{sect13titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list13style|}}}{{{content13style|}}}
|title = {{{group13|}}}{{{sect13|}}}{{{section13|}}}
|list1 = {{{list13|}}}{{{content13|}}}
|image = {{{image13|}}}
|imageleft = {{{imageleft13|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list13|}}}{{{content13|}}}
}}
|list14 =
{{#if:{{{group14|}}}{{{sect14|}}}{{{section14|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr14}}} |uncollapsed |{{{state14|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group14style|}}}{{{sect14titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list14style|}}}{{{content14style|}}}
|title = {{{group14|}}}{{{sect14|}}}{{{section14|}}}
|list1 = {{{list14|}}}{{{content14|}}}
|image = {{{image14|}}}
|imageleft = {{{imageleft14|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list14|}}}{{{content14|}}}
}}
|list15 =
{{#if:{{{group15|}}}{{{sect15|}}}{{{section15|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr15}}} |uncollapsed |{{{state15|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group15style|}}}{{{sect15titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list15style|}}}{{{content15style|}}}
|title = {{{group15|}}}{{{sect15|}}}{{{section15|}}}
|list1 = {{{list15|}}}{{{content15|}}}
|image = {{{image15|}}}
|imageleft = {{{imageleft15|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list15|}}}{{{content15|}}}
}}
|list16 =
{{#if:{{{group16|}}}{{{sect16|}}}{{{section16|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr16}}} |uncollapsed |{{{state16|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group16style|}}}{{{sect16titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list16style|}}}{{{content16style|}}}
|title = {{{group16|}}}{{{sect16|}}}{{{section16|}}}
|list1 = {{{list16|}}}{{{content16|}}}
|image = {{{image16|}}}
|imageleft = {{{imageleft16|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list16|}}}{{{content16|}}}
}}
|list17 =
{{#if:{{{group17|}}}{{{sect17|}}}{{{section17|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr17}}} |uncollapsed |{{{state17|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group17style|}}}{{{sect17titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list17style|}}}{{{content17style|}}}
|title = {{{group17|}}}{{{sect17|}}}{{{section17|}}}
|list1 = {{{list17|}}}{{{content17|}}}
|image = {{{image17|}}}
|imageleft = {{{imageleft17|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list17|}}}{{{content17|}}}
}}
|list18 =
{{#if:{{{group18|}}}{{{sect18|}}}{{{section18|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr18}}} |uncollapsed |{{{state18|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group18style|}}}{{{sect18titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list18style|}}}{{{content18style|}}}
|title = {{{group18|}}}{{{sect18|}}}{{{section18|}}}
|list1 = {{{list18|}}}{{{content18|}}}
|image = {{{image18|}}}
|imageleft = {{{imageleft18|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list18|}}}{{{content18|}}}
}}
|list19 =
{{#if:{{{group19|}}}{{{sect19|}}}{{{section19|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr19}}} |uncollapsed |{{{state19|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group19style|}}}{{{sect19titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list19style|}}}{{{content19style|}}}
|title = {{{group19|}}}{{{sect19|}}}{{{section19|}}}
|list1 = {{{list19|}}}{{{content19|}}}
|image = {{{image19|}}}
|imageleft = {{{imageleft19|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list19|}}}{{{content19|}}}
}}
|list20 =
{{#if:{{{group20|}}}{{{sect20|}}}{{{section20|}}}
| {{#invoke:navbox|navbox|child
|navbar = plain
|state = {{#ifeq:{{{selected}}}|{{{abbr20}}} |uncollapsed |{{{state20|collapsed}}}}}
|titlestyle = {{{basestyle|}}};{{{groupstyle|}}}{{{secttitlestyle|}}}{{{group20style|}}}{{{sect20titlestyle|}}}
|liststyle = {{{liststyle|}}}{{{contentstyle|}}}{{{list20style|}}}{{{content20style|}}}
|title = {{{group20|}}}{{{sect20|}}}{{{section20|}}}
|list1 = {{{list20|}}}{{{content20|}}}
|image = {{{image20|}}}
|imageleft = {{{imageleft20|}}}
|{{#if:{{{listpadding|}}} |listpadding |void}} = {{{listpadding|}}}
}}
| {{{list20|}}}{{{content20|}}}
}}
|below = {{{below|}}}
| tracking = {{{tracking|}}}
}}<noinclude>
{{documentation}}
</noinclude>
808c72ef412d47bc3360afb751d679608858d38b
Template:\
10
234
488
487
2024-08-04T12:41:34Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
/ <noinclude>
{{Documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
8cbfbe9d6f2aaa7726dfacfb2ee3c213dae39921
Module:Tlg
828
235
490
489
2024-08-04T12:41:36Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This implements Template:Tlg
local getArgs = require('Module:Arguments').getArgs
local p = {}
-- Is a string non-empty?
local function _ne(s)
return s ~= nil and s ~= ""
end
local nw = mw.text.nowiki
local function addTemplate(s)
local i, _ = s:find(':', 1, true)
if i == nil then
return 'Template:' .. s
end
local ns = s:sub(1, i - 1)
if ns == '' or mw.site.namespaces[ns] then
return s
else
return 'Template:' .. s
end
end
local function trimTemplate(s)
local needle = 'template:'
if s:sub(1, needle:len()):lower() == needle then
return s:sub(needle:len() + 1)
else
return s
end
end
local function linkTitle(args)
if _ne(args.nolink) then
return args['1']
end
local titleObj
local titlePart = '[['
if args['1'] then
-- This handles :Page and other NS
titleObj = mw.title.new(args['1'], 'Template')
else
titleObj = mw.title.getCurrentTitle()
end
titlePart = titlePart .. (titleObj ~= nil and titleObj.fullText or
addTemplate(args['1']))
local textPart = args.alttext
if not _ne(textPart) then
if titleObj ~= nil then
textPart = titleObj:inNamespace("Template") and args['1'] or titleObj.fullText
else
-- redlink
textPart = args['1']
end
end
if _ne(args.subst) then
-- HACK: the ns thing above is probably broken
textPart = 'subst:' .. textPart
end
if _ne(args.brace) then
textPart = nw('{{') .. textPart .. nw('}}')
elseif _ne(args.braceinside) then
textPart = nw('{') .. textPart .. nw('}')
end
titlePart = titlePart .. '|' .. textPart .. ']]'
if _ne(args.braceinside) then
titlePart = nw('{') .. titlePart .. nw('}')
end
return titlePart
end
function p.main(frame)
local args = getArgs(frame, {
trim = true,
removeBlanks = false
})
return p._main(args)
end
function p._main(args)
local bold = _ne(args.bold) or _ne(args.boldlink) or _ne(args.boldname)
local italic = _ne(args.italic) or _ne(args.italics)
local dontBrace = _ne(args.brace) or _ne(args.braceinside)
local code = _ne(args.code) or _ne(args.tt)
local show_result = _ne(args._show_result)
local expand = _ne(args._expand)
-- Build the link part
local titlePart = linkTitle(args)
if bold then titlePart = "'''" .. titlePart .. "'''" end
if _ne(args.nowrapname) then titlePart = '<span class="nowrap">' .. titlePart .. '</span>' end
-- Build the arguments
local textPart = ""
local textPartBuffer = "|"
local codeArguments = {}
local codeArgumentsString = ""
local i = 2
local j = 1
while args[i] do
local val = args[i]
if val ~= "" then
if _ne(args.nowiki) then
-- Unstrip nowiki tags first because calling nw on something that already contains nowiki tags will
-- mangle the nowiki strip marker and result in literal UNIQ...QINU showing up
val = nw(mw.text.unstripNoWiki(val))
end
local k, v = string.match(val, "(.*)=(.*)")
if not k then
codeArguments[j] = val
j = j + 1
else
codeArguments[k] = v
end
codeArgumentsString = codeArgumentsString .. textPartBuffer .. val
if italic then
val = '<span style="font-style:italic;">' .. val .. '</span>'
end
textPart = textPart .. textPartBuffer .. val
end
i = i + 1
end
-- final wrap
local ret = titlePart .. textPart
if not dontBrace then ret = nw('{{') .. ret .. nw('}}') end
if _ne(args.a) then ret = nw('*') .. ' ' .. ret end
if _ne(args.kbd) then ret = '<kbd>' .. ret .. '</kbd>' end
if code then
ret = '<code>' .. ret .. '</code>'
elseif _ne(args.plaincode) then
ret = '<code style="border:none;">' .. ret .. '</code>'
end
if _ne(args.nowrap) then ret = '<span class="nowrap">' .. ret .. '</span>' end
--[[ Wrap as html??
local span = mw.html.create('span')
span:wikitext(ret)
--]]
if _ne(args.debug) then ret = ret .. '\n<pre>' .. mw.text.encode(mw.dumpObject(args)) .. '</pre>' end
if show_result then
local result = mw.getCurrentFrame():expandTemplate{title = addTemplate(args[1]), args = codeArguments}
ret = ret .. " → " .. result
end
if expand then
local query = mw.text.encode('{{' .. addTemplate(args[1]) .. string.gsub(codeArgumentsString, textPartBuffer, "|") .. '}}')
local url = mw.uri.fullUrl('special:ExpandTemplates', 'wpInput=' .. query)
mw.log()
ret = ret .. " [" .. tostring(url) .. "]"
end
return ret
end
return p
2be73a9f60f9b5e8d38cbfcd220d2670c021f247
Template:整齊列表
10
236
492
491
2024-08-04T12:41:37Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:aligned table|table}}<noinclude>
{{documentation}}
</noinclude>
b46bb0255f1c93cae2a17f7589ff556cb615f050
Module:Aligned table
828
237
494
493
2024-08-04T12:41:38Z
黑茶
2
导入1个版本
Scribunto
text/plain
--本模塊嵌入{{整齊列表}}
-- This module implements {{aligned table}}
local p = {}
local function isnotempty(s)
return s and s:match( '^%s*(.-)%s*$' ) ~= ''
end
function p.table(frame)
local args = (frame.args[3] ~= nil) and frame.args or frame:getParent().args
local entries = {}
local colclass = {}
local colstyle = {}
local cols = tonumber(args['cols']) or 2
-- create the root table
local root = mw.html.create('table')
-- add table style for fullwidth
if isnotempty(args['fullwidth']) then
root
:css('width', '100%')
:css('border-collapse', 'collapse')
:css('border-spacing', '0px 0px')
:css('border', 'none')
end
-- add table classes
if isnotempty(args['class']) then
root:addClass(args['class'])
end
-- add table style
if isnotempty(args['style']) then
root:cssText(args['style'])
end
-- build arrays with the column styles and classes
if isnotempty(args['leftright']) then
colstyle[1] = 'text-align:left;'
colstyle[2] = 'text-align:right;'
end
if isnotempty(args['rightleft']) then
colstyle[1] = 'text-align:right;'
colstyle[2] = 'text-align:left;'
end
for i = 1,cols do
colclass[ i ] = colclass[ i ] or ''
colstyle[ i ] = colstyle[ i ] or ''
if isnotempty(args['colstyle']) then
colstyle[ i ] = args['colstyle'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colalign' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['colalign' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'align']) then
colstyle[ i ] = 'text-align:' .. args['col' .. tostring(i) .. 'align'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['align' .. tostring(i)]) then
colstyle[ i ] = 'text-align:' .. args['align' .. tostring(i)] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colnowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'nowrap']) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
elseif isnotempty(args['nowrap' .. tostring(i)]) then
colstyle[ i ] = 'white-space:nowrap;' .. colstyle[ i ]
end
if isnotempty(args['colwidth' .. tostring(i)]) then
colstyle[ i ] = 'width:' .. args['colwidth' .. tostring(i)] .. ';' .. colstyle[ i ]
elseif isnotempty(args['col' .. tostring(i) .. 'width']) then
colstyle[ i ] = 'width:' .. args['col' .. tostring(i) .. 'width'] .. ';' .. colstyle[ i ]
elseif isnotempty(args['colwidth']) then
colstyle[ i ] = 'width:' .. args['colwidth'] .. ';' .. colstyle[ i ]
end
if isnotempty(args['colstyle' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['colstyle' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'style']) then
colstyle[ i ] = colstyle[ i ] .. args['col' .. tostring(i) .. 'style']
elseif isnotempty(args['style' .. tostring(i)]) then
colstyle[ i ] = colstyle[ i ] .. args['style' .. tostring(i)]
end
if isnotempty(args['colclass' .. tostring(i)]) then
colclass[ i ] = args['colclass' .. tostring(i)]
elseif isnotempty(args['col' .. tostring(i) .. 'class']) then
colclass[ i ] = args['col' .. tostring(i) .. 'class']
elseif isnotempty(args['class' .. tostring(i)]) then
colclass[ i ] = args['class' .. tostring(i)]
end
end
-- compute the maximum cell index
local cellcount = 0
for k, v in pairs( args ) do
if type( k ) == 'number' then
cellcount = math.max(cellcount, k)
end
end
-- compute the number of rows
local rows = math.ceil(cellcount / cols)
-- build the table content
if isnotempty(args['title']) then
local caption = root:tag('caption')
caption:cssText(args['titlestyle'])
caption:wikitext(args['title'])
end
if isnotempty(args['above']) then
local row = root:tag('tr')
local cell = row:tag('th')
cell:attr('colspan', cols)
cell:cssText(args['abovestyle'])
cell:wikitext(args['above'])
end
for j=1,rows do
-- start a new row
local row = root:tag('tr')
if isnotempty(args['rowstyle']) then
row:cssText(args['rowstyle'])
else
row:css('vertical-align', 'top')
end
if isnotempty(args['rowclass']) then
row:addClass(args['rowclass'])
end
-- loop over the cells in the row
for i=1,cols do
local cell
if isnotempty(args['row' .. tostring(j) .. 'header']) then
cell = row:tag('th'):attr('scope','col')
elseif isnotempty(args['col' .. tostring(i) .. 'header']) then
cell = row:tag('th'):attr('scope','row')
else
cell = row:tag('td')
end
if args['class' .. tostring(j) .. '.' .. tostring(i)] then
cell:addClass(args['class' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowclass' .. tostring(j)] then
cell:addClass(args['rowclass' .. tostring(j)])
elseif args['row' .. tostring(j) .. 'class'] then
cell:addClass(args['row' .. tostring(j) .. 'class'])
elseif args['rowevenclass'] and math.fmod(j,2) == 0 then
cell:addClass(args['rowevenclass'])
elseif args['rowoddclass'] and math.fmod(j,2) == 1 then
cell:addClass(args['rowoddclass'])
end
if colclass[i] ~= '' then
cell:addClass(colclass[i])
end
end
if args['style' .. tostring(j) .. '.' .. tostring(i)] then
cell:cssText(args['style' .. tostring(j) .. '.' .. tostring(i)])
else
if args['rowstyle' .. tostring(j)] then
cell:cssText(args['rowstyle' .. tostring(j)])
elseif args['rowevenstyle'] and math.fmod(j,2) == 0 then
cell:cssText(args['rowevenstyle'])
elseif args['rowoddstyle'] and math.fmod(j,2) == 1 then
cell:cssText(args['rowoddstyle'])
elseif args['row' .. tostring(j) .. 'style'] then
cell:cssText(args['row' .. tostring(j) .. 'style'])
end
if isnotempty(colstyle[i]) then
cell:cssText(colstyle[i])
end
end
cell:wikitext(mw.ustring.gsub(args[cols*(j - 1) + i] or '', '^(.-)%s*$', '%1') or '')
end
end
-- return the root table
return tostring(root)
end
return p
fd94d5edde4bfa7d961bf37eb56377e2eff6185f
Template:Bulleted list
10
238
496
495
2024-08-04T12:41:39Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:list|bulleted}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
37ac60a83d34c2df10fb601002557ad1b55919bb
Template:Tlf
10
239
498
497
2024-08-04T12:41:39Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#Invoke:Tlg|main|nowrap=yes|nolink=yes}}</includeonly><noinclude>
{{Documentation|1=Template:Tlg/doc
|content = {{tlg/doc|tlf}}
}}
<!-- 请将分类添加至模板文档(模板文件)页面 -->
</noinclude>
67fc2af930ff6b0605dd6e34058987b73a4b1a85
Template:Template shortcut
10
240
500
499
2024-08-04T12:41:40Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div role="note" class="shortcutbox shortcutbox-left plainlist plainlinks noprint" style="<!--
-->{{#switch:{{{clear|}}} |true=clear:{{{float|right}}}; |left|right|both=clear:{{{clear|}}}; |#default=}}<!--
-->float: {{#ifeq:{{{float|}}}|left|left|right}};<!--
-->margin: {{{top|0em}}} {{#ifeq:{{{float|}}}|left|1em 0em 0em|0em 0em 1em}};<!--
-->border: 1px solid var(--border-color-base,#aaa); background: var(--background-color-base,#fff); padding: 0.3em 0.6em 0.2em 0.6em; text-align: center; font-size: 85%; font-weight: bold;color: inherit;"><!--
Adding the shortcut links:
--><div style="display: inline-block; border-bottom: 1px solid #aaa; line-height: 1.5em; font-weight: normal; margin-bottom: .2em;">{{#if:{{{redirect|}}} |重定向 |[[WP:捷徑|-{zh-hans:快捷方式; zh-hant:捷徑;}-]]}}</div> {{bulleted list
| {{#if: {{{1|<noinclude>{{PAGENAME}}</noinclude>}}} | {{{{{pre|}}}{{#ifexist:Template:{{{1}}} |[{{fullurl:Template:{{{1}}}|redirect=no}} {{#if:true|{{{1}}}}}] |[[Template:{{{1|<noinclude>{{PAGENAME}}</noinclude>}}}|{{#if:true|{{{1|<noinclude>{{PAGENAME}}</noinclude>}}}}}]]}}}} }}<!--
--> | {{#if:{{{2|}}} | {{{{{pre2|}}}{{#ifexist:Template:{{{2}}} |[{{fullurl:Template:{{{2}}}|redirect=no}} {{#if:true|{{{2}}}}}] |[[Template:{{{2}}}|{{#if:true|{{{2}}}}}]]}}}} }}<!--
--> | {{#if:{{{3|}}} | {{{{{pre3|}}}{{#ifexist:Template:{{{3}}} |[{{fullurl:Template:{{{3}}}|redirect=no}} {{#if:true|{{{3}}}}}] |[[Template:{{{3}}}|{{#if:true|{{{3}}}}}]]}}}} }}<!--
--> | {{#if:{{{4|}}} | {{{{{pre4|}}}{{#ifexist:Template:{{{4}}} |[{{fullurl:Template:{{{4}}}|redirect=no}} {{#if:true|{{{4}}}}}] |[[Template:{{{4}}}|{{#if:true|{{{4}}}}}]]}}}} }}<!--
--> | {{#if:{{{5|}}} | {{{{{pre5|}}}{{#ifexist:Template:{{{5}}} |[{{fullurl:Template:{{{5}}}|redirect=no}} {{#if:true|{{{5}}}}}] |[[Template:{{{5}}}|{{#if:true|{{{5}}}}}]]}}}} }}<!--
--> | {{#if:{{{6|}}} | {{{{{pre6|}}}{{#ifexist:Template:{{{6}}} |[{{fullurl:Template:{{{6}}}|redirect=no}} {{#if:true|{{{6}}}}}] |[[Template:{{{6}}}|{{#if:true|{{{6}}}}}]]}}}} }}<!--
--> | {{#if:{{{7|}}} | {{{{{pre7|}}}{{#ifexist:Template:{{{7}}} |[{{fullurl:Template:{{{7}}}|redirect=no}} {{#if:true|{{{7}}}}}] |[[Template:{{{7}}}|{{#if:true|{{{7}}}}}]]}}}} }}<!--
--> | {{#if:{{{8|}}} | {{{{{pre8|}}}{{#ifexist:Template:{{{8}}} |[{{fullurl:Template:{{{8}}}|redirect=no}} {{#if:true|{{{8}}}}}] |[[Template:{{{8}}}|{{#if:true|{{{8}}}}}]]}}}} }}<!--
--> | {{#if:{{{9|}}} | {{{{{pre9|}}}{{#ifexist:Template:{{{9}}} |[{{fullurl:Template:{{{9}}}|redirect=no}} {{#if:true|{{{9}}}}}] |[[Template:{{{9}}}|{{#if:true|{{{9}}}}}]]}}}} }}<!--
--> | {{#if:{{{10|}}} | {{{{{pre10|}}}{{#ifexist:Template:{{{10}}} |[{{fullurl:Template:{{{10}}}|redirect=no}} {{#if:true|{{{10}}}}}] |[[Template:{{{10}}}|{{#if:true|{{{10}}}}}]]}}}} }}<!--
-->}}<!--
--></div><noinclude>{{Documentation}}</noinclude>
27b5a406da826aed6d2cd54974d89d0d4da74869
Template:出生、逝世及日期模板
10
241
502
501
2024-08-04T12:41:40Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Navbox with collapsible groups
| name = 出生、逝世及日期模板
| state = {{{state|expanded}}}
| title = 出生、逝世及日期模板
| selected = {{{selected|{{{expanded|{{{1|}}}}}}}}}
| listclass = hlist <!-- can't see why tracking=no doesn't work, but this does -->
| tracking = <includeonly>no</includeonly>
<!----------------------------------------------------------------------------->
| abbr1 = BDA
| section1 = 出生,逝世,年龄
| content1 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|BirthDeathAge}} | Combines functions of <nowiki>{{Birth date}}, {{Birth-date}}, {{Birth date and age}}, {{Birth year and age}}, {{Death date}}, {{Death-date}}, {{Death date and age}}, and {{Death year and age}}.</nowiki>
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Birth date}} | To display a birth date and related hidden metadata.
| {{Tl|Birth-date}} |
| {{Tl|Birth date and age}} | {{Tlf|Birth date}} with suffix "(age ''N'')".
| {{Tl|Birth date and age2}} | {{Tlf|Birth date and age}} plus age as of a specified date.
| {{Tl|Birth-date and age}} | As {{Tlf|Birth date and age}} but accepts dates in text form ("15 June 1950", "June 15, 1950", "June 1950", etc).
| {{Tl|Birth year and age}} | Year of birth and approximate age.
| {{Tl|Birth based on age as of date}} | To display approximate birth year and current age given a particular date (e.g. when a dated reference mentions the age of a person).
| {{Tl|Birth date based on age at death}} | To display approximate birth year based on age at death.
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Death date}} | To display a death date and related hidden metadata.
| {{Tl|Death-date}} |
| {{Tl|Death date and age}} | {{Tlf|Death date}} with suffix "(aged ''N'')". Also called with {{tlf|event date and age}}
| {{Tl|Death-date and age}} | As {{Tlf|Death date and age}} but accepts dates in text form ("15 June 1950", "June 15, 1950", "June 1950", etc).
| {{Tl|Death date and given age}} | To display a death date and specified age.
| {{Tl|Death year and age}} | To display a year of and approximate age at death.
}}
<!----------------------------------------------------------------------------->
| abbr2 = age
| section2 = 只有年龄
| content2 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:20em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Age in years, months, weeks and days}} | Number of complete years, months, weeks and days between two dates.
| {{Tl|Age in years, months and days}} | Number of complete years, months and days between two dates.
| {{Tl|Age in years and months}} | Number of complete years and remaining months between two dates.
| {{Tl|Age in years and days}} | Number of complete years and remaining days between two dates.
| {{Tl|Age in years and days nts}} | {{Tlf|Age in years and days}} with output formatted for use in [[Help:可排序表格|number sortable tables]].
| {{Tl|Age in decimal years}} | Number of years between two dates, rounded to the specified number of decimal places.
| {{Tl|Age in years}} | Number of years between two dates.
| {{Tl|Age in years nts}} | {{Tlf|Age in years}} with output formatted for use in sortable tables.
| {{Tl|Age in months}} | Number of months between two dates.
| {{Tl|Age in weeks and days}} | Number of weeks and days between two dates.
| {{Tl|Age in weeks}} | Number of weeks between two dates.
| {{Tl|Age in days}} | Age in days between two dates.
| {{Tl|Age in days nts}} | {{Tlf|Age in days}} with output formatted for use in sortable tables.
}}
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:20em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Age}} | Age based on number of complete years between two dates.
| {{Tl|Age nts}} | {{Tlf|Age}} with output formatted for use in [[Help:可排序表格]].
| {{Tl|Age as of date}} | Current age (in years) from a known age at a specified date.
| {{Tl|Age for infant}} | Current age for infant: months and days up to one year, years and months up to three years, and years beyond age 3.
}}
<!----------------------------------------------------------------------------->
| abbr3 = dates
| section3 = 开始{{\}}结束时间
| content3 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|Start date}} / {{Tl|End date}} |
| {{Tl|Start-date}} / {{Tl|End-date}} |
| {{Tl|Start date and age}} |
| {{Tl|End date and age}} |
}}
<!----------------------------------------------------------------------------->
| abbr4 = misc
| section4 = 杂项
| content4 =
{{整齊列表|fullwidth=y
|style=line-height:1.35em;text-align:left;
|col1style=font-size:110%;white-space:nowrap;padding-right:1.0em;width:18em;
|row1style=line-height:1.6em;font-weight:bold;border-bottom:1px solid #aaa;
| 模板 | {{Resize|110%|描述{{\}}用法 }}
| {{Tl|OldStyleDate}} | Dates in [[儒略曆|Julian calendar]].
| {{Tl|OldStyleDateDY}} | As {{Tlf|OldStyleDate}} but used when Julian / [[格里曆|Gregorian date]]s fall in different years.
| {{Tl|OldStyleDateNY}} | As {{Tlf|OldStyleDate}} but without the year.
| {{Tl|Unidentified for}} |
| {{Tl|Missing for}} |
}}
<!----------------------------------------------------------------------------->
| belowclass = hlist
| belowstyle = font-weight:bold;
| below =
<!-- * [[Wikipedia:Age calculation templates|About age calculation templates]] -->
* 參見:[[:Category:日期计算模板|日期计算模板]]
}}<!--
--><noinclude>{{Documentation}}</noinclude>
76e9db694a82f0ba3efb5fa5f6116b50d3020592
Module:Transclusion count/data/B
828
242
504
503
2024-08-04T12:41:41Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
["BD"] = 17000,
["BD/isYear"] = 299000,
["BEL"] = 4300,
["BHKG"] = 2800,
["BLP"] = 30000,
["BLP_unsourced"] = 4900,
["BLPsources"] = 6200,
["BRA"] = 4100,
["BS-map"] = 2100,
["BS-map/map"] = 2100,
["Babel"] = 5000,
["Baseballstats"] = 2300,
["Based_on"] = 3800,
["Basepage_subpage"] = 115000,
["Bd"] = 299000,
["Bio_icon"] = 2500,
["Bio_icon2"] = 2500,
["Birth_date"] = 29000,
["Birth_date_and_age"] = 82000,
["Birth_year_and_age"] = 7800,
["Blist"] = 2700,
["Block"] = 4300,
["Block/styles.css"] = 4800,
["Blocked_sockpuppet"] = 15000,
["Blocked_user"] = 18000,
["Blocked_userpage_check_protection"] = 36000,
["Blp"] = 3900,
["Blpsources"] = 3600,
["Bo"] = 2500,
["Bo/raw"] = 2500,
["Bookcover"] = 2700,
["Border"] = 2500,
["Border-radius"] = 5700,
["Bot-directive-archiver"] = 3300,
["Both"] = 336000,
["Bots"] = 2500,
["Box-shadow"] = 3400,
["Br_separated_entries"] = 281000,
["Break"] = 7300,
["Broken_anchor"] = 6300,
["Broken_anchors"] = 6800,
["Bronze3"] = 2700,
["Bulleted_list"] = 5000,
["Module:Babel"] = 5000,
["Module:BaseConvert"] = 31000,
["Module:Baseball_color"] = 4300,
["Module:Baseball_color/data"] = 3200,
["Module:Based_on"] = 3800,
["Module:BigNumber"] = 7600,
["Module:BigNumber/utils"] = 7600,
["Module:Break"] = 7300,
["Module:Buffer"] = 404000,
}
2f76b71f99830169d7c0f1270ecf35b102731663
Template:Birth date and age/doc
10
243
506
505
2024-08-04T12:41:42Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>
{{#ifeq:{{#titleparts:{{PAGENAME}}|1}}|Birth date and age
| {{Template shortcut|Bda}}
| {{Template shortcut|Dob}}
}}
{{#ifeq:{{#titleparts:{{PAGENAME}}|1}}|Birth date and age
| {{High-use|45,000+}} <!--(Template:Birth date and age)-->
| {{High-use|10,000+}} <!--(Template:Birth date)-->
}}</includeonly><noinclude>{{template doc page viewed directly|{{tl|Birth date and age}}和{{tl|Birth date}}}}</noinclude>
使用模板{{tl|Birth date and age}}將會顯示出生日期,並在其後自動計算並加註今年的年齡。{{tl|Birth date}}是一个用法相似的模板,但不会加注年龄。
如果知道出生日,但只欲顯示出生年份,請使用{{tl|Birth year and age confirmed}}。如果不知道出生日,只知道出生年份(含月份),請使用{{tl|Birth year and age}}。
== 使用說明 ==
{| class="plainlinksneverexpand noprint" style="margin-top:0; width:100%; text-align:center;border:1px #ddd solid;border-radius:5px;"
|-
! style="background:#dfd;border-radius:5px;"|本頁說明全部範例所使用的今天日期是<br>
{{CURRENTYEAR}}年{{CURRENTMONTHNAME}}{{CURRENTDAY}}日
|}
請使用以下原始碼:
: <code><nowiki>{{Birth date|year=|month=|day=}}</nowiki></code>
: <code><nowiki>{{Birth date and age|year=|month=|day=}}</nowiki></code>
其中:
* '''year''':出生西元年份(請填寫四位數的阿拉伯數字,不須加上「年」)
* '''month''':出生月份(請填寫阿拉伯數字,不須加上「月」)
* '''day''':出生日(請填寫阿拉伯數字,不須加上「日」)
== 範例 ==
'''例1''',使用:
<pre>{{Birth date and age|year=1993|month=2|day=24}}</pre>
页面上显示为:
{{Birth date and age|year=1993|month=2|day=24}}
'''例2''',也可以省略變數名稱,例如:
<pre>{{Birth date and age|1993|2|24}}</pre>
页面上显示为:
{{Birth date and age|1993|2|24}}
'''例3''',若使用:
<pre>{{Birth date|1993|02|24}}</pre>
则页面上显示为:
{{Birth date|1993|2|24}}
== 重定向 ==
{{tl|生日和年齡}}重定向至{{tl|Birth date and age}}。
== 参见 ==
* {{tl|Death date and age}},用于显示某人去世日期与年龄。
* {{tl|Start date and age}},傳回日期和它距離今天的時間長度。
{{出生、逝世及日期模板|BDA}}
<includeonly>{{Sandbox other||<!-- 本行下加入模板的分類 -->
[[Category:日期计算模板|{{PAGENAME}}]]
[[Category:生卒模板|{{PAGENAME}}]]
}}</includeonly>
<templatedata>
{
"params": {
"year": {
"label": "出生年份",
"description": "请填写四位数的阿拉伯数字,不须加上“年”",
"type": "number",
"required": true
},
"day": {
"label": "出生日",
"description": "请填写阿拉伯数字,不须加上“日”",
"type": "number",
"suggested": true
},
"month": {
"label": "出生月份",
"description": "请填写阿拉伯数字,不须加上“月”",
"type": "number",
"suggested": true
}
},
"description": "显示出生日期,并在其后自动计算并加注今年的年龄。如果知道出生日,但只欲显示出生年份,请使用{{Birth year and age confirmed}}。如果不知道出生日,只知道出生年份,请使用{{Birth year and age}}。",
"maps": {
"生日和年齡": {},
"生日和年齡 ": {}
},
"paramOrder": [
"year",
"day",
"month"
],
"format": "inline"
}
</templatedata>
a9efb19968a3733e12487d43bf41563ddf2cd231
MediaWiki:Sidebar
8
244
508
2024-08-04T13:09:08Z
黑茶
2
创建页面,内容为“ * navigation ** mainpage|mainpage-description ** recentchanges-url|recentchanges ** templateimport-url|templateimport ** randompage-url|randompage ** helppage|help-mediawiki * SEARCH * TOOLBOX * LANGUAGES”
wikitext
text/x-wiki
* navigation
** mainpage|mainpage-description
** recentchanges-url|recentchanges
** templateimport-url|templateimport
** randompage-url|randompage
** helppage|help-mediawiki
* SEARCH
* TOOLBOX
* LANGUAGES
eef003e759fe82e11d71995b18e0dbe125692cd2
MediaWiki:Templateimport-url
8
245
509
2024-08-04T13:10:23Z
黑茶
2
创建页面,内容为“那艺娜维基:模板导入请求”
wikitext
text/x-wiki
那艺娜维基:模板导入请求
8251830cc890d989b07c7251ed0fbe99ec954e8f
MediaWiki:Templateimport
8
246
510
2024-08-04T13:11:10Z
黑茶
2
创建页面,内容为“模版导入请求”
wikitext
text/x-wiki
模版导入请求
ed1766ae6972c372d524ecb06b595df50644e457
Template:Bot
10
247
512
511
2024-08-04T13:14:25Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{ombox
|image = [[File:{{{image|{{#switch: {{lc:{{{status}}}}}
|active
|approved = Crystal Clear accepted bot.png
|trial = Crystal Clear question bot.svg
|inactive = Crystal Clear inactive bot2.png
|unapproved = Crystal Clear denied bot.png
|#default = Crystal Clear action run.png
}}}}}|75px|{{{caption|This is a bot account.}}}|alt={{{alt|}}}]]
|text = '''此為[[那艺娜维基:Bot policy|機械人帳號]]{{#if:{{{codebase|}}}
|,使用{{{codebase}}}
|{{#ifeq: {{lc:{{{awb}}}}}|yes
|,使用[[WP:AWB|自動維基瀏覽器]]
}}}},操作者為{{{by|[[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User:{{Trim|{{{1}}}}}|{{Trim|{{{1}}}}}]]([[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User talk:{{{talklink|{{Trim|{{{1}}}}}}}}|討論]]){{#if:{{Trim|{{{2|}}}}}
|{{#if:{{Trim|{{{3|}}}}}
|、
|及
}}[[:zh:User:{{Trim|{{{2}}}}}|{{Trim|{{{2}}}}}]]([[:zh:User talk:{{{talklink|{{Trim|{{{2}}}}}}}}|討論]])
}}{{#if:{{Trim|{{{3|}}}}}
|及[[:zh:User:{{Trim|{{{3}}}}}|{{Trim|{{{3}}}}}]]([[:en:User talk:{{{talklink|{{Trim|{{{3}}}}}}}}|討論]])
}}}}},'''屬[[WP:SOCK#LEGIT|合規附屬帳戶]],以半自動或全自動方式協助用戶處理繁瑣而重複的工作。{{#switch: {{lc:{{{status}}}}}
|active
|approved = {{#if:{{{globalbot|}}}
|此為[{{fullurl:Special:GlobalUsers/Global_bot|limit=1&username={{urlencode:{{{username|{{BASEPAGENAME}}}}}}}}} 全域機械人],主要依據[[:meta:Bot_policy#Global_bots|元維基機械人方針]]處理跨語言連結或整理雙重重定向,現時在用。{{#if:{{{overridebrfa|}}}|另外,此帳戶亦會處理其他本地事務或者得到本地許可,詳請[[{{{overridebrfa}}}|見此]]。|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|另外,此帳戶得到本地許可,詳情[[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|見此]]。|}}}}
|{{#ifeq:{{{approvalneeded|}}}|no
| 此機械人在用,而所處理事務毋須事先取得[[WP:BRFA|許可]]。
| 此機械人已得到許可,亦正在運作中。{{#if:{{{overridebrfa|}}}|[[WP:BRFA|申請存檔]][[{{{overridebrfa}}}|見此]]|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|[[WP:BRFA|申請存檔]][[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|見此]]|{{{nocat|[[Category:無指明申請許可而在用維基百科機械人]]}}}}}}}
}}
}}{{{nocat|[[Category:在用維基百科機械人]]}}}
|inactive = {{#ifeq:{{{approvalneeded|}}}|no
| 此機械人現時不在用,而之前所負責事務毋須事先得到許可。
| 此機械人現時不在用,然而仍保有{{#if:{{{globalbot|}}}|全域|}}社群[[{{#if:{{{overridebrfa|}}}|{{{overridebrfa}}}|那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}}}|許可]]。{{{nocat|[[Category:不在用維基百科機械人]]}}}
}}
|trial = 此機械人獲得[[那艺娜维基:機械人審核小組|機械人審核小組]]批准有限度試行。{{{nocat|[[Category:未批准維基百科機械人]]}}}
|unapproved = 此機械人並未獲得社群批准運作,或其操作許可已被撤銷,是故不應進行大規模操作,亦請勿在缺乏操作者監察下運作,操作者及机器人用戶空間除外。{{{nocat|[[Category:未批准維基百科機械人]]}}}
|#default = {{{nocat|<includeonly>[[Category:未知狀態維基百科機械人]]</includeonly>}}}
}}{{{more|}}}<br/><small>{{#ifeq:{{lc:{{{awb}}}}}|yes
|如要使此機械人停止運作直至操作者重啟,請編輯[[User talk:{{PAGENAME}}|機械人討論頁]]。如果討論頁為重定向,請直接編輯重定向本身,而非所指向的頁面。
}} <span class="sysop-show">'''管理員︰若然此機械人{{#ifeq: {{lc:{{{status}}}}}|unapproved
|進行大規模操作或相信在缺乏監察下運作,而且所編輯區域並非操作者或機械人用戶名字空間
|{{#ifeq:{{lc:{{{awb}}}}}|yes
|在收到提醒或警告訊息後繼續作出有問題編輯
|失靈或作出有問題編輯
}}
}},請[{{fullurl:Special:Block|wpTarget={{PAGENAMEE}}&wpExpiry=indefinite&wpHardBlock=1&wpAutoBlock=0&wpCreateAccount=0&wpReason=機器人發生故障並必須緊急停止}} 施予封禁]{{#ifeq:{{lc:{{{awb}}}}}|yes
|或者移除其[[那艺娜维基:AutoWikiBrowser/CheckPage|自動維基瀏覽器使用權]]
}}。'''</span></small>
|imageright={{#ifeq: {{lc:{{{awb}}}}}|yes
|[[File:AWB_logo_draft.png|75px]]{{{nocat|[[Category:自动维基浏览器使用者]]}}}
}}<includeonly>{{{nocat|[[Category:所有維基百科機器人]]{{#if:{{{globalbot|}}}|[[Category:全域維基百科機械人]][[Category:跨語言連接機械人]]|}}}}}</includeonly>
}}<noinclude>
{{documentation}}
</noinclude>
7c7dede67ac480f0382c74e9c6950f0d2f9ec71f
Template:If empty
10
248
514
513
2024-08-04T13:14:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{<includeonly>safesubst:</includeonly>#invoke:If empty|main}}<noinclude>{{Documentation}}</noinclude>
745940b7bdde8a1585c887ee4ee5ce81d98461a4
Template:Trim
10
249
516
515
2024-08-04T13:14:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{ {{{|safesubst:}}}#if:1|{{{1|}}}}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
80cbf249bdbb60b46ba41f0d928c8f463c62983e
Module:If empty
828
250
518
517
2024-08-04T13:14:30Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:If empty', removeBlanks = false})
local lastk = 0
for k,v in ipairs(args) do
if v ~= '' then
return v
end
lastk = k
end
end
return p
4bfc0c7c8bf3b63144db1ea12f2260db00421233
Template:Cmbox
10
251
520
519
2024-08-04T13:14:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<templatestyles src="Cmbox/style.css" />
{{#invoke:Message box|cmbox}}<noinclude>
{{documentation}}
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. -->
</noinclude>
b4b6273c788f27ebde512d666f392db572fabea8
Template:Ifempty
10
252
522
521
2024-08-04T13:14:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:If empty]]
462862e6cf0a8b300838914bb395b8c0207abdcc
Template:Small
10
253
524
523
2024-08-04T13:14:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<small>{{{1}}}</small><noinclude>
<!--Categories and interwikis go in the /doc sub-page.-->
{{Documentation|Template:Resize/doc}}
</noinclude>
ae7e668fc4870d13635bf6ddc8c1ae29f59df592
Template:Tlp
10
254
526
525
2024-08-04T13:14:36Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span style="white-space:nowrap;">{{{{#if:{{{1|}}}
| [[{{ns:Template}}:{{{1}}}|{{{1}}}]] | tlp|... }}<!--
-->{{#ifeq:{{{2|x}}}|{{{2|}}}| |{{{2}}} }}<!--
-->{{#ifeq:{{{3|x}}}|{{{3|}}}| |{{{3}}} }}<!--
-->{{#ifeq:{{{4|x}}}|{{{4|}}}| |{{{4}}} }}<!--
-->{{#ifeq:{{{5|x}}}|{{{5|}}}| |{{{5}}} }}<!--
-->{{#ifeq:{{{6|x}}}|{{{6|}}}| |{{{6}}} }}<!--
-->{{#ifeq:{{{7|x}}}|{{{7|}}}| |{{{7}}} }}<!--
-->{{#ifeq:{{{8|x}}}|{{{8|}}}| |{{{8}}} }}<!--
-->{{#ifeq:{{{9|x}}}|{{{9|}}}| |{{{9}}} }}<!--
-->}}</span><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
832a834204d293def8f65d96e27ed3f9464fc6d8
Template:Bot use warning
10
255
528
527
2024-08-04T13:14:37Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{Cmbox
|image=[[File:Kawaii robot power clipart.svg|80px|link=那艺娜维基:机器人|alt=]]
|type=notice
|text=<div style="text-align: center;"><span style="font-size: larger;">'''有[[那艺娜维基:机器人|機器人]]使用{{{namespace|本{{Namespace pagename}}}}}{{#ifeq:{{{subcats|}}}|yes|和其子分類}}'''</span>
-----
{{Small|如欲移動、刪除或修改{{{namespace|此{{Namespace pagename}}}}}而無法[[向下兼容|-{zh-hans: 向下兼容; zh-hant:向下相容; }-]],並會影響機器人運作,請先通知機器人操作者,謝謝您。}}{{#if:{{{bot|{{{bots|}}}}}}|{{Small|相關的機器人:{{{bot|{{{bots}}}}}}}}}}</div>}}<includeonly>{{Sandbox other||[[Category:維基百科機器人作業用頁面]]}}</includeonly><noinclude>
{{Documentation}}</noinclude>
9ed7f494880808db1ebcc011fed735628e567783
Template:Bot/doc
10
256
530
529
2024-08-04T13:14:37Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{Documentation subpage}}</noinclude>
{{Bot use warning|bots=[[User:Cewbot]]。}}
<!-- 在本行下編輯模板說明 -->
== 參數及使用方法 ==
; 1 : 第一個參數為機械人操作者。<br />The first unnamed parameter specifies the operator of the bot.
; 2, 3 : 如有需要,第二及第三個參數為其他機械人共同操作者。<br />The second and third unnamed parameters can be used to specify co-operators of the bot, if required.
; site : 操作者如無本地帳戶,則可輸入兩個字母語言代碼。<br />The two letter code for those operators that do not have an account on the English language Wikipedia (though having a local account is strongly recommended).
; status : ''active''(在用而且已得到批准)、 ''inactive''(得到批准但不在用)、''trial''(測試中)或''unapproved''(未批准或許可已撤銷)<br />''active'' (and approved), ''inactive'' (but approved), ''trial'' or ''unapproved''
; awb : ''yes'' (如有使用[[那艺娜维基:AutoWikiBrowser|AWB]])或留空(如果並非使用AWB)<br />''yes'' (if this bot uses [[那艺娜维基:AutoWikiBrowser|AWB]]), or omit (if it doesn't).
; codebase: 機械人所使用程序語言(例如︰[[mw:Pywikibot|Pywikibot]]、[[m:perlwikipedia|perlWikipedia]]……)<br />The name of the code (programming or scripting language) used to create the bot (e.g., [[mw:Pywikibot|Pywikibot]], [[m:perlwikipedia|perlWikipedia]], ...)
; brfa : '''選填'''︰如有,就會更改內鏈連接,否則就會連接到<nowiki>{{BASEPAGENAME}}</nowiki>。<br />''Optional'' if specified, overrides the name of the request for approval. If not specified, defaults to <nowiki>{{BASEPAGENAME}}</nowiki>
; by : '''選填'''︰如有就會蓋過頭三個參數,即1,2及3,改為顯示此參數所帶內容。<br />''Optional'' if specified, overrides the usual display of the operator's username in the first line generated from the three unnamed parameters.
; approvalneeded : 如果上面'''status'''標記為「active/approved」,而且在此參數輸入<kbd>yes</kbd>,則模板會標示該機械人所執行事項為毋須事先取得批准。<br />If '''status''' indicated ''active/approved'', setting <kbd>yes</kbd> will make the template indicate that the bot is running tasks for which no approval is needed.
; overridebrfa : 如果機械人曾經遞交過幾項申請、得到過幾次批准或有幾項工作,而預設BRFA連結未能夠顯示所有已批准申請或工作,則可在此參數輸入其他維基百科頁面連結。此參數會蓋過'''brfa'''。<br />If the bot has multiple requests or approval, or multiple tasks, and the default BRFA link cannot link to a page that contains all the bot's approved requests or tasks, this field allows inputting a link to any Wikipedia page. Specifying this field overrides '''brfa'''.
; more : 其他額外資訊,通常不用,因為{{para|status}}、{{para|brfa}}及{{para|approvalneeded}}已包含大部分資訊。<br />Any ''additional'' information to specify in the mbox. Usually not needed, since {{para|status}}, {{para|brfa}}, and {{para|approvalneeded}} covers most cases.
; alt : '''選填'''︰圖檔替代文字。<br />Optional alternate text for the image.
== 範例 ==
<!-- for the documentation don't subst the result -->
{| class="wikitable mbox-inside"
|-
! Code
! Result
|-
| <code>{{tlp|{{BASEPAGENAME}}|Example}}</code>
|
{{{{BASEPAGENAME}}|Example|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|awb=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|awb=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|codebase=[[m:perlwikipedia|perlWikipedia]]</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en |codebase=[[m:perlwikipedia|perlWikipedia]]|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=active</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=trial</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=trial|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=inactive</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=inactive|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=unapproved</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=unapproved|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|status=active|globalbot=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|globalbot=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|image=Crystal Clear question bot.svg</nowiki><br /><nowiki>|more=此機器人正在測試中。</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|image=Crystal Clear question bot.svg|more=此機器人正在測試中。|nocat=}}
|}
== 參見 ==
* {{tl|User bot owner}}
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[那艺娜维基:Wikidata]]) -->
[[Category:維基百科機器人模板|{{PAGENAME}}]]
}}</includeonly>
6629e6cd5ddae698eb3a64247873c22620e7bb32
533
530
2024-08-04T13:15:13Z
黑茶
2
wikitext
text/x-wiki
<noinclude>{{Documentation subpage}}</noinclude>
<!-- 在本行下編輯模板說明 -->
== 參數及使用方法 ==
; 1 : 第一個參數為機械人操作者。<br />The first unnamed parameter specifies the operator of the bot.
; 2, 3 : 如有需要,第二及第三個參數為其他機械人共同操作者。<br />The second and third unnamed parameters can be used to specify co-operators of the bot, if required.
; site : 操作者如無本地帳戶,則可輸入兩個字母語言代碼。<br />The two letter code for those operators that do not have an account on the English language Wikipedia (though having a local account is strongly recommended).
; status : ''active''(在用而且已得到批准)、 ''inactive''(得到批准但不在用)、''trial''(測試中)或''unapproved''(未批准或許可已撤銷)<br />''active'' (and approved), ''inactive'' (but approved), ''trial'' or ''unapproved''
; awb : ''yes'' (如有使用[[那艺娜维基:AutoWikiBrowser|AWB]])或留空(如果並非使用AWB)<br />''yes'' (if this bot uses [[那艺娜维基:AutoWikiBrowser|AWB]]), or omit (if it doesn't).
; codebase: 機械人所使用程序語言(例如︰[[mw:Pywikibot|Pywikibot]]、[[m:perlwikipedia|perlWikipedia]]……)<br />The name of the code (programming or scripting language) used to create the bot (e.g., [[mw:Pywikibot|Pywikibot]], [[m:perlwikipedia|perlWikipedia]], ...)
; brfa : '''選填'''︰如有,就會更改內鏈連接,否則就會連接到<nowiki>{{BASEPAGENAME}}</nowiki>。<br />''Optional'' if specified, overrides the name of the request for approval. If not specified, defaults to <nowiki>{{BASEPAGENAME}}</nowiki>
; by : '''選填'''︰如有就會蓋過頭三個參數,即1,2及3,改為顯示此參數所帶內容。<br />''Optional'' if specified, overrides the usual display of the operator's username in the first line generated from the three unnamed parameters.
; approvalneeded : 如果上面'''status'''標記為「active/approved」,而且在此參數輸入<kbd>yes</kbd>,則模板會標示該機械人所執行事項為毋須事先取得批准。<br />If '''status''' indicated ''active/approved'', setting <kbd>yes</kbd> will make the template indicate that the bot is running tasks for which no approval is needed.
; overridebrfa : 如果機械人曾經遞交過幾項申請、得到過幾次批准或有幾項工作,而預設BRFA連結未能夠顯示所有已批准申請或工作,則可在此參數輸入其他維基百科頁面連結。此參數會蓋過'''brfa'''。<br />If the bot has multiple requests or approval, or multiple tasks, and the default BRFA link cannot link to a page that contains all the bot's approved requests or tasks, this field allows inputting a link to any Wikipedia page. Specifying this field overrides '''brfa'''.
; more : 其他額外資訊,通常不用,因為{{para|status}}、{{para|brfa}}及{{para|approvalneeded}}已包含大部分資訊。<br />Any ''additional'' information to specify in the mbox. Usually not needed, since {{para|status}}, {{para|brfa}}, and {{para|approvalneeded}} covers most cases.
; alt : '''選填'''︰圖檔替代文字。<br />Optional alternate text for the image.
== 範例 ==
<!-- for the documentation don't subst the result -->
{| class="wikitable mbox-inside"
|-
! Code
! Result
|-
| <code>{{tlp|{{BASEPAGENAME}}|Example}}</code>
|
{{{{BASEPAGENAME}}|Example|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|awb=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|awb=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|codebase=[[m:perlwikipedia|perlWikipedia]]</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en |codebase=[[m:perlwikipedia|perlWikipedia]]|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=active</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=trial</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=trial|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=inactive</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=inactive|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en|status=unapproved</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=unapproved|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|site=en</nowiki><br /><nowiki>|status=active|globalbot=yes</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|site=en|status=active|globalbot=yes|nocat=}}
|-
| <code>{{tlp|{{BASEPAGENAME}}|<nowiki>John Smith|image=Crystal Clear question bot.svg</nowiki><br /><nowiki>|more=此機器人正在測試中。</nowiki>}}</code>
|
{{{{BASEPAGENAME}}|John Smith|image=Crystal Clear question bot.svg|more=此機器人正在測試中。|nocat=}}
|}
== 參見 ==
* {{tl|User bot owner}}
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[那艺娜维基:Wikidata]]) -->
[[Category:維基百科機器人模板|{{PAGENAME}}]]
}}</includeonly>
bcf9ca3a4b3fdf64fb3598e87ea7a586620b5f5f
Template:Cmbox/style.css
10
257
532
531
2024-08-04T13:14:38Z
黑茶
2
导入1个版本
sanitized-css
text/css
.cmbox {
margin: 3px 0;
border-collapse: collapse;
border: 1px solid #a2a9b1;
background-color: #dfe8ff; /* Default "notice" blue */
box-sizing: border-box;
}
.cmbox-speedy {
border: 4px solid #b32424; /* Red */
background-color: #ffdbdb; /* Pink */
}
.cmbox-delete {
background-color: #ffdbdb; /* Pink */
}
.cmbox-content {
background-color: #ffe7ce; /* Orange */
}
.cmbox-style {
background-color: #fff9db; /* Yellow */
}
.cmbox-move {
background-color: #e4d8ff; /* Purple */
}
.cmbox-protection {
background-color: #efefe1; /* Gray-gold */
}
.cmbox .mbox-text {
border: none;
/* @noflip */
padding: 0.25em 0.9em;
width: 100%;
}
.cmbox .mbox-image {
border: none;
/* @noflip */
padding: 2px 0 2px 0.9em;
text-align: center;
}
.cmbox .mbox-imageright {
border: none;
/* @noflip */
padding: 2px 0.9em 2px 0;
text-align: center;
}
/* An empty narrow cell */
.cmbox .mbox-empty-cell {
border: none;
padding: 0;
width: 1px;
}
.cmbox .mbox-invalid-type {
text-align: center;
}
@media (min-width: 720px) {
.cmbox {
margin: 3px 10%;
}
}
/* flipped lightness in hsl space except the main cmbox is the main page blue */
html.skin-theme-clientpref-night .cmbox {
background-color: #0d1a27; /* Default "notice" blue */
}
html.skin-theme-clientpref-night .cmbox-speedy,
html.skin-theme-clientpref-night .cmbox-delete {
background-color: #300; /* Pink */
}
html.skin-theme-clientpref-night .cmbox-content {
background-color: #331a00; /* Orange */
}
html.skin-theme-clientpref-night .cmbox-style {
background-color: #332b00; /* Yellow */
}
html.skin-theme-clientpref-night .cmbox-move {
background-color: #08001a; /* Purple */
}
html.skin-theme-clientpref-night .cmbox-protection {
background-color: #212112; /* Gray-gold */
}
@media (prefers-color-scheme: dark) {
html.skin-theme-clientpref-os .cmbox {
background-color: #0d1a27; /* Default "notice" blue */
}
html.skin-theme-clientpref-os .cmbox-speedy,
html.skin-theme-clientpref-os .cmbox-delete {
background-color: #300; /* Pink */
}
html.skin-theme-clientpref-os .cmbox-content {
background-color: #331a00; /* Orange */
}
html.skin-theme-clientpref-os .cmbox-style {
background-color: #332b00; /* Yellow */
}
html.skin-theme-clientpref-os .cmbox-move {
background-color: #08001a; /* Purple */
}
html.skin-theme-clientpref-os .cmbox-protection {
background-color: #212112; /* Gray-gold */
}
}
714e8d532c88a9aad9fc9fdcf152d0044514034c
User:黑茶-Bot
2
258
534
2024-08-04T13:18:33Z
黑茶-Bot
4
创建页面,内容为“{{Bot}}”
wikitext
text/x-wiki
{{Bot}}
ef2cc9740ad9747fedea8d2edbc61bcbb91ce3a0
535
534
2024-08-04T13:24:52Z
黑茶
2
wikitext
text/x-wiki
{{Bot|黑茶|status=inactive}}
9bad9a44e7232086983b27f300fbeae5942b4e67
Template:Bot
10
247
536
512
2024-08-04T13:25:56Z
黑茶
2
wikitext
text/x-wiki
{{ombox
|image = [[File:{{{image|{{#switch: {{lc:{{{status}}}}}
|active
|approved = Crystal Clear accepted bot.png
|trial = Crystal Clear question bot.svg
|inactive = Crystal Clear inactive bot2.png
|unapproved = Crystal Clear denied bot.png
|#default = Crystal Clear action run.png
}}}}}|75px|{{{caption|This is a bot account.}}}|alt={{{alt|}}}]]
|text = '''此为[[那艺娜维基:Bot policy|机械人帐号]]{{#if:{{{codebase|}}}
|,使用{{{codebase}}}
|{{#ifeq: {{lc:{{{awb}}}}}|yes
|,使用[[WP:AWB|自动维基浏览器]]
}}}},操作者为{{{by|[[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User:{{Trim|{{{1}}}}}|{{Trim|{{{1}}}}}]]([[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User talk:{{{talklink|{{Trim|{{{1}}}}}}}}|讨论]]){{#if:{{Trim|{{{2|}}}}}
|{{#if:{{Trim|{{{3|}}}}}
|、
|及
}}[[:User:{{Trim|{{{2}}}}}|{{Trim|{{{2}}}}}]]([[:User talk:{{{talklink|{{Trim|{{{2}}}}}}}}|讨论]])
}}{{#if:{{Trim|{{{3|}}}}}
|及[[:User:{{Trim|{{{3}}}}}|{{Trim|{{{3}}}}}]]([[:en:User talk:{{{talklink|{{Trim|{{{3}}}}}}}}|讨论]])
}}}}},'''属[[WP:SOCK#LEGIT|合规附属帐户]],以半自动或全自动方式协助用户处理繁琐而重複的工作。{{#switch: {{lc:{{{status}}}}}
|active
|approved = {{#if:{{{globalbot|}}}
|此为[{{fullurl:Special:GlobalUsers/Global_bot|limit=1&username={{urlencode:{{{username|{{BASEPAGENAME}}}}}}}}} 全域机械人],主要依据[[:meta:Bot_policy#Global_bots|元维基机械人方针]]处理跨语言连结或整理双重重定向,现时在用。{{#if:{{{overridebrfa|}}}|另外,此帐户亦会处理其他本地事务或者得到本地许可,详请[[{{{overridebrfa}}}|见此]]。|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|另外,此帐户得到本地许可,详情[[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|见此]]。|}}}}
|{{#ifeq:{{{approvalneeded|}}}|no
| 此机械人在用,而所处理事务毋须事先取得[[WP:BRFA|许可]]。
| 此机械人已得到许可,亦正在运作中。{{#if:{{{overridebrfa|}}}|[[WP:BRFA|申请存档]][[{{{overridebrfa}}}|见此]]|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|[[WP:BRFA|申请存档]][[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|见此]]|{{{nocat|[[Category:无指明申请许可而在用维基百科机械人]]}}}}}}}
}}
}}{{{nocat|[[Category:在用维基百科机械人]]}}}
|inactive = {{#ifeq:{{{approvalneeded|}}}|no
| 此机械人现时不在用,而之前所负责事务毋须事先得到许可。
| 此机械人现时不在用,然而仍保有{{#if:{{{globalbot|}}}|全域|}}社群[[{{#if:{{{overridebrfa|}}}|{{{overridebrfa}}}|那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}}}|许可]]。{{{nocat|[[Category:不在用维基百科机械人]]}}}
}}
|trial = 此机械人获得[[那艺娜维基:机械人审核小组|机械人审核小组]]批准有限度试行。{{{nocat|[[Category:未批准维基百科机械人]]}}}
|unapproved = 此机械人并未获得社群批准运作,或其操作许可已被撤销,是故不应进行大规模操作,亦请勿在缺乏操作者监察下运作,操作者及机器人用户空间除外。{{{nocat|[[Category:未批准维基百科机械人]]}}}
|#default = {{{nocat|<includeonly>[[Category:未知状态维基百科机械人]]</includeonly>}}}
}}{{{more|}}}<br/><small>{{#ifeq:{{lc:{{{awb}}}}}|yes
|如要使此机械人停止运作直至操作者重启,请编辑[[User talk:{{PAGENAME}}|机械人讨论页]]。如果讨论页为重定向,请直接编辑重定向本身,而非所指向的页面。
}} <span class="sysop-show">'''管理员︰若然此机械人{{#ifeq: {{lc:{{{status}}}}}|unapproved
|进行大规模操作或相信在缺乏监察下运作,而且所编辑区域并非操作者或机械人用户名字空间
|{{#ifeq:{{lc:{{{awb}}}}}|yes
|在收到提醒或警告讯息后继续作出有问题编辑
|失灵或作出有问题编辑
}}
}},请[{{fullurl:Special:Block|wpTarget={{PAGENAMEE}}&wpExpiry=indefinite&wpHardBlock=1&wpAutoBlock=0&wpCreateAccount=0&wpReason=机器人发生故障并必须紧急停止}} 施予封禁]{{#ifeq:{{lc:{{{awb}}}}}|yes
|或者移除其[[那艺娜维基:AutoWikiBrowser/CheckPage|自动维基浏览器使用权]]
}}。'''</span></small>
|imageright={{#ifeq: {{lc:{{{awb}}}}}|yes
|[[File:AWB_logo_draft.png|75px]]{{{nocat|[[Category:自动维基浏览器使用者]]}}}
}}<includeonly>{{{nocat|[[Category:所有维基百科机器人]]{{#if:{{{globalbot|}}}|[[Category:全域维基百科机械人]][[Category:跨语言连接机械人]]|}}}}}</includeonly>
}}<noinclude>
{{documentation}}
</noinclude>
0a22cad93b5b305b978b22074866ccdcb022826a
537
536
2024-08-04T13:28:49Z
黑茶
2
wikitext
text/x-wiki
{{ombox
|image = [[File:{{{image|{{#switch: {{lc:{{{status}}}}}
|active
|approved = Crystal Clear accepted bot.png
|trial = Crystal Clear question bot.svg
|inactive = Crystal Clear inactive bot2.png
|unapproved = Crystal Clear denied bot.png
|#default = Crystal Clear action run.png
}}}}}|75px|{{{caption|This is a bot account.}}}|alt={{{alt|}}}]]
|text = '''此为机械人帐号{{#if:{{{codebase|}}}
|,使用{{{codebase}}}
|{{#ifeq: {{lc:{{{awb}}}}}|yes
|,使用[[WP:AWB|自动维基浏览器]]
}}}},操作者为{{{by|[[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User:{{Trim|{{{1}}}}}|{{Trim|{{{1}}}}}]]([[:{{#if:{{{site|}}}
|{{{site}}}
|zh
}}:User talk:{{{talklink|{{Trim|{{{1}}}}}}}}|讨论]]){{#if:{{Trim|{{{2|}}}}}
|{{#if:{{Trim|{{{3|}}}}}
|、
|及
}}[[:User:{{Trim|{{{2}}}}}|{{Trim|{{{2}}}}}]]([[:User talk:{{{talklink|{{Trim|{{{2}}}}}}}}|讨论]])
}}{{#if:{{Trim|{{{3|}}}}}
|及[[:User:{{Trim|{{{3}}}}}|{{Trim|{{{3}}}}}]]([[:en:User talk:{{{talklink|{{Trim|{{{3}}}}}}}}|讨论]])
}}}}},'''属[[WP:SOCK#LEGIT|合规附属帐户]],以半自动或全自动方式协助用户处理繁琐而重複的工作。{{#switch: {{lc:{{{status}}}}}
|active
|approved = {{#if:{{{globalbot|}}}
|此为[{{fullurl:Special:GlobalUsers/Global_bot|limit=1&username={{urlencode:{{{username|{{BASEPAGENAME}}}}}}}}} 全域机械人],主要依据[[:meta:Bot_policy#Global_bots|元维基机械人方针]]处理跨语言连结或整理双重重定向,现时在用。{{#if:{{{overridebrfa|}}}|另外,此帐户亦会处理其他本地事务或者得到本地许可,详请[[{{{overridebrfa}}}|见此]]。|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|另外,此帐户得到本地许可,详情[[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|见此]]。|}}}}
|{{#ifeq:{{{approvalneeded|}}}|no
| 此机械人在用,而所处理事务毋须事先取得[[WP:BRFA|许可]]。
| 此机械人已得到许可,亦正在运作中。{{#if:{{{overridebrfa|}}}|[[WP:BRFA|申请存档]][[{{{overridebrfa}}}|见此]]|{{#ifexist:那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|[[WP:BRFA|申请存档]][[那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}|见此]]|{{{nocat|[[Category:无指明申请许可而在用维基百科机械人]]}}}}}}}
}}
}}{{{nocat|[[Category:在用维基百科机械人]]}}}
|inactive = {{#ifeq:{{{approvalneeded|}}}|no
| 此机械人现时不在用,而之前所负责事务毋须事先得到许可。
| 此机械人现时不在用,然而仍保有{{#if:{{{globalbot|}}}|全域|}}社群[[{{#if:{{{overridebrfa|}}}|{{{overridebrfa}}}|那艺娜维基:机器人/申请/{{ifempty|{{{brfa|}}}|{{BASEPAGENAME}}}}}}|许可]]。{{{nocat|[[Category:不在用维基百科机械人]]}}}
}}
|trial = 此机械人获得[[那艺娜维基:机械人审核小组|机械人审核小组]]批准有限度试行。{{{nocat|[[Category:未批准维基百科机械人]]}}}
|unapproved = 此机械人并未获得社群批准运作,或其操作许可已被撤销,是故不应进行大规模操作,亦请勿在缺乏操作者监察下运作,操作者及机器人用户空间除外。{{{nocat|[[Category:未批准维基百科机械人]]}}}
|#default = {{{nocat|<includeonly>[[Category:未知状态维基百科机械人]]</includeonly>}}}
}}{{{more|}}}<br/><small>{{#ifeq:{{lc:{{{awb}}}}}|yes
|如要使此机械人停止运作直至操作者重启,请编辑[[User talk:{{PAGENAME}}|机械人讨论页]]。如果讨论页为重定向,请直接编辑重定向本身,而非所指向的页面。
}} <span class="sysop-show">'''管理员︰若然此机械人{{#ifeq: {{lc:{{{status}}}}}|unapproved
|进行大规模操作或相信在缺乏监察下运作,而且所编辑区域并非操作者或机械人用户名字空间
|{{#ifeq:{{lc:{{{awb}}}}}|yes
|在收到提醒或警告讯息后继续作出有问题编辑
|失灵或作出有问题编辑
}}
}},请[{{fullurl:Special:Block|wpTarget={{PAGENAMEE}}&wpExpiry=indefinite&wpHardBlock=1&wpAutoBlock=0&wpCreateAccount=0&wpReason=机器人发生故障并必须紧急停止}} 施予封禁]{{#ifeq:{{lc:{{{awb}}}}}|yes
|或者移除其[[那艺娜维基:AutoWikiBrowser/CheckPage|自动维基浏览器使用权]]
}}。'''</span></small>
|imageright={{#ifeq: {{lc:{{{awb}}}}}|yes
|[[File:AWB_logo_draft.png|75px]]{{{nocat|[[Category:自动维基浏览器使用者]]}}}
}}<includeonly>{{{nocat|[[Category:所有维基百科机器人]]{{#if:{{{globalbot|}}}|[[Category:全域维基百科机械人]][[Category:跨语言连接机械人]]|}}}}}</includeonly>
}}<noinclude>
{{documentation}}
</noinclude>
e548822f121426ac7256bfe68bdc4a62de7f189b
那艺娜
0
171
538
507
2024-08-04T13:34:25Z
黑茶
2
修正参考资料
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 参考资料 ==
{{Reflist}}
09f381907d7528a12fbbc217b1e99a4278525532
539
538
2024-08-04T13:37:00Z
黑茶
2
添加分类
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 参考资料 ==
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈]]
2432daf50fce154f132c804201652c8c6d197a69
Template:Userbox
10
259
541
540
2024-08-04T14:03:10Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:userbox|userbox}}<noinclude>{{doc}}</noinclude>
d5a8edeeebb1c69bbe874bb8206bd663042b933b
Template:ISO 639 name
10
260
543
542
2024-08-04T14:03:14Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{ISO 639 name {{{1|undefined}}}}}</includeonly><noinclude>
{{Documentation}}
</noinclude>
5a97bd834fc99f9308b9143563978662c4387811
Module:Unsubst
828
261
545
544
2024-08-04T14:03:15Z
黑茶
2
导入1个版本
Scribunto
text/plain
local p = {}
local specialParams = {
['$N'] = 'template name', -- Deprecated, but keeping until it is removed from transcluding templates
['$B'] = 'template content',
}
p[''] = function ( frame )
if not frame:getParent() then
error( '{{#invoke:Unsubst|}} makes no sense without a parent frame' )
end
if not frame.args['$B'] then
error( '{{#invoke:Unsubst|}} requires parameter $B (template content)' )
end
if mw.isSubsting() then
---- substing
-- Combine passed args with passed defaults
local args = {}
for k, v in pairs( frame.args ) do
if not specialParams[k] then
if v == '__DATE__' then
v = mw.getContentLanguage():formatDate( 'Y年n月' )
end
args[k] = v
end
end
for k, v in pairs( frame:getParent().args ) do
args[k] = v
end
-- Build an equivalent template invocation
-- First, find the title to use
local titleobj = mw.title.new(frame:getParent():getTitle())
local title
if titleobj.namespace == 10 then -- NS_TEMPLATE
title = titleobj.text
elseif titleobj.namespace == 0 then -- NS_MAIN
title = ':' .. titleobj.text
else
title = titleobj.prefixedText
end
-- Build the invocation body with numbered args first, then named
local ret = '{{' .. title
for k, v in ipairs( args ) do
if string.find( v, '=', 1, true ) then
-- likely something like 1=foo=bar, we need to do it as a named arg
break
end
ret = ret .. '|' .. v
args[k] = nil
end
for k, v in pairs( args ) do
ret = ret .. '|' .. k .. '=' .. v
end
return ret .. '}}'
else
---- Not substing
-- Just return the "body"
return frame.args['$B'] .. (frame.args['$N'] and frame:getParent():getTitle() == mw.title.getCurrentTitle().prefixedText and '[[Category:使用$N的Module:Unsubst调用]]' or '')
end
end
return p
e8abf58ec4f76139537c53e4f6005c233e38d6d8
Template:Category handler
10
262
547
546
2024-08-04T14:03:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:
{{#ifeq: {{lc: {{{nocat|}}} }} | true
| dontcat <!--"nocat=true", don't categorize-->
}}{{#ifeq: {{lc: {{{categories|}}} }} | no
| dontcat
}}{{#switch: {{lc: {{{category2|¬}}} }}
| yes
| ¬ = <!--Not defined-->
| #default = dontcat <!--"category2 = no/'defined but empty'/'anything'"-->
}}{{#switch: {{lc: {{{subpage|}}} }}
| no =
{{basepage subpage
|
| dontcat <!--"subpage=no" and on a subpage-->
| page = {{{page|}}} <!--For testing-->
}}
| only =
{{basepage subpage
| dontcat <!--"subpage=only" and not on a subpage-->
| page = {{{page|}}} <!--For testing-->
}}
}}
| <!--Don't categorise (result was "dontcat" or "dontcatdontcat" and so on)-->
| <!--Check blacklist-->
{{#switch:
{{#ifeq: {{lc: {{{nocat|}}} }} | false
| <!--"nocat=false", skip blacklist check-->
| {{#ifeq: {{lc: {{{categories|}}} }} | yes
| <!--Skip blacklist check-->
| {{#ifeq: {{lc: {{{category2|}}} }} | yes
| <!--Skip blacklist check-->
| {{category handler/blacklist| page = {{{page|}}} }} <!--Check blacklist-->
}}
}}
}}
| hide = <!--Blacklist returned "hide", don't categorize-->
| #default =
<!--Check if any namespace parameter is defined-->
{{#ifeq: h0#384!5nea+w9 | {{{all| {{{main| {{{talk| {{{user| {{{wikipedia| {{{file| {{{mediawiki| {{{template| {{{help| {{{category| {{{portal| {{{book| {{{wikiproject| {{{other| h0#384!5nea+w9 }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}} }}}
| <!--No namespace parameters fed, basic usage-->
{{namespace detect
| main = {{{1|}}}
| file = {{{1|}}}
| help = {{{1|}}}
| category = {{{1|}}}
| portal = {{{1|}}}
| book = {{{1|}}}
| wikiproject = {{{1|}}}
| page = {{{page|}}} <!--For testing and demonstration-->
}}
| <!--Namespace parameters fed, advanced usage.
If "data" is a number, return the corresponding
numbered parameter, else return "data". -->
{{{all|}}}{{category handler/numbered
| 1 = {{{1|}}}
| 2 = {{{2|}}}
| 3 = {{{3|}}}
| 4 = {{{4|}}}
| 5 = {{{5|}}}
| 6 = {{{6|}}}
| 7 = {{{7|}}}
| 8 = {{{8|}}}
| 9 = {{{9|}}}
| 10 = {{{10|}}}
| data =
<!--Check what namespace, and return the data for it.
Respecting empty parameters on purpose. -->
{{namespace detect
| main = {{{main| {{{other|}}} }}}
| talk = {{{talk| {{{other|}}} }}}
| user = {{{user| {{{other|}}} }}}
| wikipedia = {{{wikipedia| {{{project| {{{other|}}} }}} }}}
| file = {{{file| {{{image| {{{other|}}} }}} }}}
| mediawiki = {{{mediawiki| {{{other|}}} }}}
| template = {{{template| {{{other|}}} }}}
| help = {{{help| {{{other|}}} }}}
| category = {{{category| {{{other|}}} }}}
| portal = {{{portal| {{{other|}}} }}}
| book = {{{book| {{{other|}}} }}}
| wikiproject = {{{wikiproject| {{{other|}}} }}}
| other = {{{other|}}} <!--Namespace special or a new namespace-->
| page = {{{page|}}} <!--For testing and demonstration-->
}}
}}
}}
}}
}}<noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, and interwikis to Wikidata. -->
</noinclude>
c2dcb69c376e6ebdc4b416dc054b6152efc98920
Template:Category handler/blacklist
10
263
549
548
2024-08-04T14:03:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>'''Actual code of this blacklist:'''<pre></noinclude>{{if pagename
<!-- Start of blacklist -->
| Main Page = hide <!-- Don't categorise the main page -->
<!-- Don't categorise on centralised cascade page or its subpages -->
| Wikipedia:Cascade-protected items/+ = hide
<!-- Don't categorise userboxes in their own "template space" -->
| User:UBX/+ = hide
| User talk:UBX/+ = hide
| Wikipedia:Template messages/* = hide <!-- Don't categorise on its subpages -->
| /archiv* = hide <!-- Don't categorise on /archive pages -->
<!-- End of blacklist -->
| page = {{{page|}}} <!-- Never change this one, see the doc -->
}}<noinclude></pre>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
b152c913c7d6755273326ec0648587b9b18d2979
Template:If pagename
10
264
551
550
2024-08-04T14:03:16Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:When pagename is]]
ce7deb49fcb3beb9fcd9da7cc735815712d4498a
Template:When pagename is
10
265
553
552
2024-08-04T14:03:17Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:x <!--Remove surrounding whitespace-->
| <!--Check for match with full pagename-->
{{{ {{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }} <!--Has data, or is empty but defined-->
| <!--Check for match with "User:Somepage/+"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|1|1}}/+
| <!--Else, are we on a subpage or a basepage?-->
{{#if:{{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|2}}
| <!--We are on a subpage, check for match with "User:Somepage/*"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|1|1}}/*
| <!--Check for match with "Somepage/*"-->
{{{ {{#titleparts:{{#if:{{{page|}}}| {{PAGENAME:{{{page|}}}}} | {{PAGENAME}} }}|1|1}}/*
| <!--Check for match with "/something"-->
{{{ /{{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}
| <!--Check for match with "/somethin*"-->
{{{ /{{lc: {{padleft:|8| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}*
| <!--Check for match with "/someth*"-->
{{{ /{{lc: {{padleft:|6| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}*
| <!--Check for match with "/some*"-->
{{{ /{{lc: {{padleft:|4| {{#titleparts:{{#if:{{{page|}}}| {{{page|}}} | {{FULLPAGENAME}} }}|0|-1}}# }} }}* <!--Pad with # so "/a" doesn't match "/aaaa*"-->
| {{{subpage| {{{other|}}} }}} <!--Respecting empty parameter on purpose-->
}}}
}}}
}}}
}}}
}}}
}}}
| <!--We are on a basepage, check for match with "Somepage"-->
{{{ {{#if:{{{page|}}}| {{PAGENAME:{{{page|}}}}} | {{PAGENAME}} }}
| {{{basepage| {{{other|}}} }}} <!--Respecting empty parameter on purpose-->
}}}
}} <!--End if, are we on a subpage or a basepage?-->
}}}
}}}
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
cb8a18bf89fe47e27ba71ad692df00ef7313b9a4
Template:Category handler/numbered
10
266
555
554
2024-08-04T14:03:17Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#iferror: {{#expr: 1 + {{{data|}}} }}
| {{{data|}}} <!--Not a number, return "data" as is-->
| {{{ {{{data|}}} |}}} <!--"data" is a number, return that numbered parameter-->
}}<noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
48d906542dfe053be2e00190637ed322717506f9
Template:Namespace detect
10
267
557
556
2024-08-04T14:03:17Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch:
{{lc: <!--Lower case the result-->
<!--If no or empty "demospace" parameter then detect namespace-->
{{#if:{{{demospace|}}}
| {{{demospace}}}
| {{#ifeq:{{NAMESPACE}}|{{ns:0}}
| main
| {{#ifeq:{{NAMESPACE}}|{{TALKSPACE}}
| talk
| {{NAMESPACE}}
}}
}}
}}
}}
| main = {{#switch:{{str mid|{{FULLPAGENAME}}||{{#expr:abs({{str find|{{FULLPAGENAME}}|:}})-1}}}}<!--
---->| MOS = {{{pseudo| {{{mos| {{{other|}}} }}} }}}<!--
---->| LTA = {{{pseudo| {{{lta| {{{other|}}} }}} }}}<!--
---->| NT = {{{pseudo| {{{nt| {{{other|}}} }}} }}}<!--
---->| NC = {{{pseudo| {{{nc| {{{other|}}} }}} }}}<!--
---->| #default = {{{main| {{{other|}}} }}}<!--
---->}}
| talk = {{{talk| {{{other|}}} }}}
| user = {{{user| {{{other|}}} }}}
| wikipedia = {{{wikipedia| {{{other|}}} }}}
| image = {{{image| {{{other|}}} }}}
| mediawiki = {{{mediawiki| {{{other|}}} }}}
| template = {{{template| {{{other|}}} }}}
| help = {{{help| {{{other|}}} }}}
| category = {{{category| {{{other|}}} }}}
| portal = {{{portal| {{{other|}}} }}}
| wikiproject = {{{wikiproject| {{{other|}}} }}}
| other
| #default = {{{other|}}}
}}<!--End switch--><noinclude>
{{documentation}}
<!-- Add categories to the /doc subpage, and interwikis to Wikidata. -->
</noinclude>
f1961a31d9c2e2c54d527eb6206563f5626ce288
Module:Color contrast
828
268
559
558
2024-08-04T14:03:19Z
黑茶
2
导入1个版本
Scribunto
text/plain
--
-- This module implements
-- {{Color contrast ratio}}
-- {{Greater color contrast ratio}}
-- {{ColorToLum}}
-- {{RGBColorToLum}}
--
local p = {}
local HTMLcolor = mw.loadData( 'Module:Color contrast/colors' )
local function sRGB (v)
if (v <= 0.03928) then
v = v / 12.92
else
v = math.pow((v+0.055)/1.055, 2.4)
end
return v
end
local function rgbdec2lum(R, G, B)
if ( 0 <= R and R < 256 and 0 <= G and G < 256 and 0 <= B and B < 256 ) then
return 0.2126 * sRGB(R/255) + 0.7152 * sRGB(G/255) + 0.0722 * sRGB(B/255)
else
return ''
end
end
local function hsl2lum(h, s, l)
if ( 0 <= h and h < 360 and 0 <= s and s <= 1 and 0 <= l and l <= 1 ) then
local c = (1 - math.abs(2*l - 1))*s
local x = c*(1 - math.abs( math.fmod(h/60, 2) - 1) )
local m = l - c/2
local r, g, b = m, m, m
if( 0 <= h and h < 60 ) then
r = r + c
g = g + x
elseif( 60 <= h and h < 120 ) then
r = r + x
g = g + c
elseif( 120 <= h and h < 180 ) then
g = g + c
b = b + x
elseif( 180 <= h and h < 240 ) then
g = g + x
b = b + c
elseif( 240 <= h and h < 300 ) then
r = r + x
b = b + c
elseif( 300 <= h and h < 360 ) then
r = r + c
b = b + x
end
return rgbdec2lum(255*r, 255*g, 255*b)
else
return ''
end
end
local function color2lum(c)
if (c == nil) then
return ''
end
-- html '#' entity
c = c:gsub("#", "#")
-- whitespace
c = c:match( '^%s*(.-)[%s;]*$' )
-- unstrip nowiki strip markers
c = mw.text.unstripNoWiki(c)
-- lowercase
c = c:lower()
-- first try to look it up
local L = HTMLcolor[c]
if (L ~= nil) then
return L
end
-- convert from hsl
if mw.ustring.match(c,'^hsl%([%s]*[0-9][0-9%.]*[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local h, s, l = mw.ustring.match(c,'^hsl%([%s]*([0-9][0-9%.]*)[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return hsl2lum(tonumber(h), tonumber(s)/100, tonumber(l)/100)
end
-- convert from rgb
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*,[%s]*[0-9][0-9]*[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*,[%s]*([0-9][0-9]*)[%s]*%)$')
return rgbdec2lum(tonumber(R), tonumber(G), tonumber(B))
end
-- convert from rgb percent
if mw.ustring.match(c,'^rgb%([%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*,[%s]*[0-9][0-9%.]*%%[%s]*%)$') then
local R, G, B = mw.ustring.match(c,'^rgb%([%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*,[%s]*([0-9][0-9%.]*)%%[%s]*%)$')
return rgbdec2lum(255*tonumber(R)/100, 255*tonumber(G)/100, 255*tonumber(B)/100)
end
-- remove leading # (if there is one) and whitespace
c = mw.ustring.match(c, '^[%s#]*([a-f0-9]*)[%s]*$')
-- split into rgb
local cs = mw.text.split(c or '', '')
if( #cs == 6 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[2])
local G = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[4])
local B = 16*tonumber('0x' .. cs[5]) + tonumber('0x' .. cs[6])
return rgbdec2lum(R, G, B)
elseif ( #cs == 3 ) then
local R = 16*tonumber('0x' .. cs[1]) + tonumber('0x' .. cs[1])
local G = 16*tonumber('0x' .. cs[2]) + tonumber('0x' .. cs[2])
local B = 16*tonumber('0x' .. cs[3]) + tonumber('0x' .. cs[3])
return rgbdec2lum(R, G, B)
end
-- failure, return blank
return ''
end
-- This exports the function for use in other modules.
-- The colour is passed as a string.
function p._lum(color)
return color2lum(color)
end
function p._greatercontrast(args)
local bias = tonumber(args['bias'] or '0') or 0
local css = (args['css'] and args['css'] ~= '') and true or false
local v1 = color2lum(args[1] or '')
local c2 = args[2] or '#FFFFFF'
local v2 = color2lum(c2)
local c3 = args[3] or '#000000'
local v3 = color2lum(c3)
local ratio1 = -1;
local ratio2 = -1;
if (type(v1) == 'number' and type(v2) == 'number') then
ratio1 = (v2 + 0.05)/(v1 + 0.05)
ratio1 = (ratio1 < 1) and 1/ratio1 or ratio1
end
if (type(v1) == 'number' and type(v3) == 'number') then
ratio2 = (v3 + 0.05)/(v1 + 0.05)
ratio2 = (ratio2 < 1) and 1/ratio2 or ratio2
end
if css then
local c1 = args[1] or ''
if mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c1, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c1 = '#' .. c1
end
if mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(c2, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c2 = '#' .. c2
end
if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then
c3 = '#' .. c3
end
return 'background-color:' .. c1 .. '; color:' .. ((ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or '') .. ';'
end
return (ratio1 > 0) and (ratio2 > 0) and ((ratio1 + bias > ratio2) and c2 or c3) or ''
end
function p._ratio(args)
local v1 = color2lum(args[1])
local v2 = color2lum(args[2])
if (type(v1) == 'number' and type(v2) == 'number') then
-- v1 should be the brighter of the two.
if v2 > v1 then
v1, v2 = v2, v1
end
return (v1 + 0.05)/(v2 + 0.05)
else
return args['error'] or '?'
end
end
function p._styleratio(args)
local style = (args[1] or ''):lower()
local bg, fg = 'white', 'black'
local lum_bg, lum_fg = 1, 0
if args[2] then
local lum = color2lum(args[2])
if lum ~= '' then bg, lum_bg = args[2], lum end
end
if args[3] then
local lum = color2lum(args[3])
if lum ~= '' then fg, lum_fg = args[3], lum end
end
local slist = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(style or '', '&#[Xx]23;', '#'), '#', '#'), ';')
for k = 1,#slist do
local s = slist[k]
local k,v = s:match( '^[%s]*([^:]-):([^:]-)[%s;]*$' )
k = k or ''
v = v or ''
if (k:match('^[%s]*(background)[%s]*$') or k:match('^[%s]*(background%-color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_bg = v, lum end
elseif (k:match('^[%s]*(color)[%s]*$')) then
local lum = color2lum(v)
if( lum ~= '' ) then bg, lum_fg = v, lum end
end
end
if lum_bg > lum_fg then
return (lum_bg + 0.05)/(lum_fg + 0.05)
else
return (lum_fg + 0.05)/(lum_bg + 0.05)
end
end
--[[
Use {{#invoke:Color contrast|somecolor}} directly or
{{#invoke:Color contrast}} from a wrapper template.
Parameters:
-- |1= — required; A color to check.
--]]
function p.lum(frame)
local color = frame.args[1] or frame:getParent().args[1]
return p._lum(color)
end
function p.ratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._ratio(args)
end
function p.styleratio(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._styleratio(args)
end
function p.greatercontrast(frame)
local args = frame.args[1] and frame.args or frame:getParent().args
return p._greatercontrast(args)
end
return p
1e399769117591366a63f62996c9a407077cc711
Module:Color contrast/colors
828
269
561
560
2024-08-04T14:03:20Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
aliceblue = 0.92880068253475,
antiquewhite = 0.84646951707754,
aqua = 0.7874,
aquamarine = 0.8078549208338,
azure = 0.97265264954166,
beige = 0.8988459998705,
bisque = 0.80732327372979,
black = 0,
blanchedalmond = 0.85084439608156,
blue = 0.0722,
blueviolet = 0.12622014321946,
brown = 0.098224287876511,
burlywood = 0.51559844533893,
cadetblue = 0.29424681085422,
chartreuse = 0.76032025902623,
chocolate = 0.23898526114557,
coral = 0.37017930872924,
cornflowerblue = 0.30318641994179,
cornsilk = 0.93562110372965,
crimson = 0.16042199953026,
cyan = 0.7874,
darkblue = 0.018640801980939,
darkcyan = 0.20329317839046,
darkgoldenrod = 0.27264703559993,
darkgray = 0.39675523072563,
darkgreen = 0.091143429047575,
darkgrey = 0.39675523072563,
darkkhaki = 0.45747326349994,
darkmagenta = 0.07353047651207,
darkolivegreen = 0.12651920884889,
darkorange = 0.40016167026524,
darkorchid = 0.13413142174857,
darkred = 0.054889674531132,
darksalmon = 0.40541471563381,
darkseagreen = 0.43789249325969,
darkslateblue = 0.065792846227988,
darkslategray = 0.067608151928044,
darkslategrey = 0.067608151928044,
darkturquoise = 0.4874606277449,
darkviolet = 0.10999048339343,
deeppink = 0.23866895828276,
deepskyblue = 0.44481603395575,
dimgray = 0.14126329114027,
dimgrey = 0.14126329114027,
dodgerblue = 0.27442536991456,
firebrick = 0.10724525535015,
floralwhite = 0.95922484825004,
forestgreen = 0.18920812076002,
fuchsia = 0.2848,
gainsboro = 0.71569350050648,
ghostwhite = 0.94311261886323,
gold = 0.69860877428159,
goldenrod = 0.41919977809569,
gray = 0.2158605001139,
green = 0.15438342968146,
greenyellow = 0.80609472611453,
grey = 0.2158605001139,
honeydew = 0.96336535554782,
hotpink = 0.34658438169715,
indianred = 0.21406134963884,
indigo = 0.03107561486337,
ivory = 0.99071270600615,
khaki = 0.77012343394121,
lavender = 0.80318750514521,
lavenderblush = 0.90172748631046,
lawngreen = 0.73905893124963,
lemonchiffon = 0.94038992245622,
lightblue = 0.63709141280807,
lightcoral = 0.35522120733135,
lightcyan = 0.94587293494829,
lightgoldenrodyellow = 0.93348351018297,
lightgray = 0.65140563741982,
lightgreen = 0.69091979956865,
lightgrey = 0.65140563741982,
lightpink = 0.58566152734898,
lightsalmon = 0.4780675225206,
lightseagreen = 0.35050145117042,
lightskyblue = 0.56195637618331,
lightslategray = 0.23830165007287,
lightslategrey = 0.23830165007287,
lightsteelblue = 0.53983888284666,
lightyellow = 0.98161818392882,
lime = 0.7152,
limegreen = 0.44571042246098,
linen = 0.88357340984379,
magenta = 0.2848,
maroon = 0.045891942324215,
mediumaquamarine = 0.49389703310801,
mediumblue = 0.044077780212328,
mediumorchid = 0.21639251153773,
mediumpurple = 0.22905858091648,
mediumseagreen = 0.34393112338131,
mediumslateblue = 0.20284629471622,
mediumspringgreen = 0.70704308194184,
mediumturquoise = 0.5133827926448,
mediumvioletred = 0.14371899849357,
midnightblue = 0.02071786635086,
mintcream = 0.97834604947588,
mistyrose = 0.82183047859185,
moccasin = 0.80083000991567,
navajowhite = 0.76519682342785,
navy = 0.015585128108224,
oldlace = 0.91900633405549,
olive = 0.20027537200568,
olivedrab = 0.22593150951929,
orange = 0.4817026703631,
orangered = 0.25516243753416,
orchid = 0.31348806761439,
palegoldenrod = 0.78792647887614,
palegreen = 0.77936759006353,
paleturquoise = 0.76436077921714,
palevioletred = 0.28754994117889,
papayawhip = 0.87797100199835,
peachpuff = 0.74905589878251,
peru = 0.30113074877936,
pink = 0.63271070702466,
plum = 0.45734221587969,
powderblue = 0.68254586500605,
purple = 0.061477070432439,
rebeccapurple = 0.07492341159447,
red = 0.2126,
rosybrown = 0.32319457649407,
royalblue = 0.16663210743188,
saddlebrown = 0.097922285020521,
salmon = 0.36977241527596,
sandybrown = 0.46628543696283,
seagreen = 0.19734199706275,
seashell = 0.92737862206922,
sienna = 0.13697631337098,
silver = 0.52711512570581,
skyblue = 0.55291668518184,
slateblue = 0.14784278062136,
slategray = 0.20896704076536,
slategrey = 0.20896704076536,
snow = 0.96533341834849,
springgreen = 0.73052306068529,
steelblue = 0.20562642207625,
tan = 0.48237604163921,
teal = 0.16996855778968,
thistle = 0.56818401093733,
tomato = 0.30638612719415,
turquoise = 0.5895536427578,
violet = 0.40315452986676,
wheat = 0.74909702820482,
white = 1,
whitesmoke = 0.91309865179342,
yellow = 0.9278,
yellowgreen = 0.50762957208707,
}
6ae47fdb24de4eed5ec26d203faf5341a388987b
Template:Fix
10
270
563
562
2024-08-04T14:03:20Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch:{{{subst|¬}}}
|¬={{category handler
|template=[[Category:需要检查替代引用的模板]]
|nocat={{{nocat|<noinclude>true</noinclude>}}}
}}
|SUBST=[[Category:錯誤使用替換引用的頁面]]
}}{{Category handler
|main={{Fix/category
|cat-date={{{cat-date|}}}
|cat={{{cat|}}}
|cat-date2={{{cat-date2|}}}
|cat2={{{cat2|}}}
|cat-date3={{{cat-date3|}}}
|cat3={{{cat3|}}}
|date={{{date|}}}
}}
|template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:包含缺少日期的清理标记的模板]]}}}}}}
|subpage=no
}}{{#if:{{{text|}}}
|<sup class="noprint Inline-Template {{{class|}}}" style="white-space:nowrap;">[{{#if:{{{pre-text|}}}
|{{{pre-text}}}
}}[[{{{link|Wikipedia:清理}}}|<span title="{{#if:{{{date|}}}|自{{{date}}}}}{{{title|{{{link|需要清理}}}}}}">{{{text|}}}</span>]]{{#if:{{{post-text|}}}
|{{{post-text}}}
}}]</sup>|{{{special|}}}
}}<noinclude>
{{Documentation}}
<!-- Add cats and interwikis to the /doc subpage, not here! -->
</noinclude>
93c3a5ef6bac7207480de71b0a2d1e25fc466a13
Template:Basepage subpage
10
271
565
564
2024-08-04T14:03:21Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:When on basepage]]
89cca1422cd3731b93eaaf5aadbe96cee6f121ff
Template:When on basepage
10
272
567
566
2024-08-04T14:03:21Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch:
<!--If no or empty "page" parameter then detect
basepage/subpage/subsubpage-->
{{#if:{{{page|}}}
| {{#if:{{#titleparts:{{{page}}}|0|3}}
| subsubpage <!--Subsubpage or lower-->
| {{#if:{{#titleparts:{{{page}}}|0|2}}
| subpage
| basepage
}}
}}
| {{#if:{{#titleparts:{{FULLPAGENAME}}|0|3}}
| subsubpage <!--Subsubpage or lower-->
| {{#if:{{#titleparts:{{FULLPAGENAME}}|0|2}}
| subpage
| basepage
}}
}}
}}
| basepage = {{{1|}}}
| subpage = {{{2|}}}
| subsubpage = {{{3| {{{2|}}} }}} <!--Respecting empty parameter on purpose-->
}}<!--End switch--><noinclude>
{{Documentation}}
</noinclude>
cf4dc92df647a26ab0ce149772a1fe3ac6c3dfc0
Template:Fix/category
10
273
569
568
2024-08-04T14:03:21Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{pp-template|small=yes}}</noinclude>{{{cat|<includeonly>[[Category:需要清理的条目]]</includeonly>}}}{{#if:{{{cat-date|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}{{#if:{{{cat2|}}}|{{{cat2}}}}}{{#if:{{{cat-date2|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date2}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date2}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}{{#if:{{{cat3|}}}|{{{cat3}}}}}{{#if:{{{cat-date3|}}}
|[[Category:{{#if:{{{date|}}}
|自{{{date}}}
}}{{{cat-date3}}}]]{{#if:{{{date|}}}
|{{#ifexist:Category:自{{{date}}}{{{cat-date3}}}|
|[[Category:在模板中使用无效日期参数的条目]]
}}
}}
}}
5aba2c0a3df1f67b5f8d45eb6c2506f0b99faebc
Module:Userbox
828
274
571
570
2024-08-04T14:03:24Z
黑茶
2
导入1个版本
Scribunto
text/plain
-- This module implements {{userbox}}.
local categoryHandler = require('Module:Category handler').main
local p = {}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function checkNum(val, default)
-- Checks whether a value is a number greater than or equal to zero. If so,
-- returns it as a number. If not, returns a default value.
val = tonumber(val)
if val and val >= 0 then
return val
else
return default
end
end
local function addSuffix(num, suffix)
-- Turns a number into a string and adds a suffix.
if num then
return tostring(num) .. suffix
else
return nil
end
end
local function checkNumAndAddSuffix(num, default, suffix)
-- Checks a value with checkNum and adds a suffix.
num = checkNum(num, default)
return addSuffix(num, suffix)
end
local function makeCat(cat, sort)
-- Makes a category link.
if sort then
return mw.ustring.format('[[Category:%s|%s]]', cat, sort)
else
return mw.ustring.format('[[Category:%s]]', cat)
end
end
--------------------------------------------------------------------------------
-- Argument processing
--------------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
return function (frame)
local origArgs = require('Module:Arguments').getArgs(frame)
local args = {}
for k, v in pairs(origArgs) do
args[k] = v
end
return p.main(funcName, args)
end
end
p.userbox = makeInvokeFunc('_userbox')
p['userbox-2'] = makeInvokeFunc('_userbox-2')
p['userbox-r'] = makeInvokeFunc('_userbox-r')
--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------
function p.main(funcName, args)
local userboxData = p[funcName](args)
local userbox = p.render(userboxData)
local cats = p.categories(args)
return userbox .. (cats or '')
end
function p._userbox(args)
-- Does argument processing for {{userbox}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args[1] or args['border-c'] or args['id-c'] or '#999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
data.infoClass = args['info-class']
-- Get id values.
local id = args.logo or args[3] or args.id
data.id = id
data.showId = id and true or false
data.idWidth = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.idBackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.idTextAlign = args['id-a'] or 'center'
data.idFontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.idColor = args['logo-color'] or args['id-fc'] or data.infoColor
data.idPadding = args['logo-padding'] or args['id-p'] or '0 1px 0 0'
data.idLineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.idOtherParams = args['logo-other-param'] or args['id-op']
data.idClass = args['id-class']
return data
end
p['_userbox-2'] = function (args)
-- Does argument processing for {{userbox-2}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args[9] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args[1] or args['border-c'] or args['id1-c'] or '#999999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args[2] or args['info-c'] or '#eeeeee'
-- Get info values.
data.info = args[4] or args.info or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-s'], 8, 'pt')
data.infoColor = args[8] or args['info-fc'] or 'black'
data.infoPadding = args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-lh'] or '1.25em'
data.infoOtherParams = args['info-op']
-- Get id values.
data.showId = true
data.id = args.logo or args[3] or args.id1 or 'id1'
data.idWidth = checkNumAndAddSuffix(args['id1-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['id-h'], 45, 'px')
data.idBackgroundColor = args[1] or args['id1-c'] or '#dddddd'
data.idTextAlign = 'center'
data.idFontSize = checkNumAndAddSuffix(args['id1-s'], 14, 'pt')
data.idLineHeight = args['id1-lh'] or '1.25em'
data.idColor = args['id1-fc'] or data.infoColor
data.idPadding = args['id1-p'] or '0 1px 0 0'
data.idOtherParams = args['id1-op']
-- Get id2 values.
data.showId2 = true
data.id2 = args.logo or args[5] or args.id2 or 'id2'
data.id2Width = checkNumAndAddSuffix(args['id2-w'], 45, 'px')
data.id2Height = data.idHeight
data.id2BackgroundColor = args[7] or args['id2-c'] or args[1] or '#dddddd'
data.id2TextAlign = 'center'
data.id2FontSize = checkNumAndAddSuffix(args['id2-s'], 14, 'pt')
data.id2LineHeight = args['id2-lh'] or '1.25em'
data.id2Color = args['id2-fc'] or data.infoColor
data.id2Padding = args['id2-p'] or '0 0 0 1px'
data.id2OtherParams = args['id2-op']
return data
end
p['_userbox-r'] = function (args)
-- Does argument processing for {{userbox-r}}.
local data = {}
-- Get div tag values.
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args[1] or args['border-c'] or args['id-c'] or '#999'
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'
-- Get id values.
data.showId = false -- We only show id2 in userbox-r.
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-align'] or args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
-- Get id2 values.
data.showId2 = true
data.id2 = args.logo or args[3] or args.id or 'id'
data.id2Width = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.id2Height = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.id2BackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.id2TextAlign = args['id-a'] or 'center'
data.id2FontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.id2Color = args['logo-color'] or args['id-fc'] or data.infoColor
data.id2Padding = args['logo-padding'] or args['id-p'] or '0 0 0 1px'
data.id2LineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.id2OtherParams = args['logo-other-param'] or args['id-op']
return data
end
function p.render(data)
-- Renders the userbox html using the content of the data table.
-- Render the div tag html.
local root = mw.html.create('div')
root
:css('float', data.float)
:css('border', (data.borderWidth or '') .. ' solid ' .. (data.borderColor or ''))
:css('margin', '1px')
:css('width', data.width)
:addClass('wikipediauserbox skin-invert ')
:addClass(data.bodyClass)
-- Render the table tag html.
local tableroot = root:tag('table')
tableroot
:attr('role', 'presentation')
:css('border-collapse', 'collapse')
:css('width', data.width)
:css('margin-bottom', '0')
:css('margin-top', '0')
:css('background', data.backgroundColor)
-- Render the id html.
local tablerow = tableroot:tag('tr')
if data.showId then
tablerow:tag('td')
:css('border', '0')
:css('width', data.idWidth)
:css('height', data.idHeight)
:css('background', data.idBackgroundColor)
:css('text-align', data.idTextAlign)
:css('font-size', data.idFontSize)
:css('font-weight', 'bold')
:css('color', data.idColor)
:css('padding', data.idPadding)
:css('line-height', data.idLineHeight)
:css('vertical-align', 'middle')
:cssText(data.idOtherParams)
:addClass(data.idClass)
:wikitext(data.id)
end
-- Render the info html.
tablerow:tag('td')
:css('border', '0')
:css('text-align', data.infoTextAlign)
:css('font-size', data.infoFontSize)
:css('padding', data.infoPadding)
:css('height', data.infoHeight)
:css('line-height', data.infoLineHeight)
:css('color', data.infoColor)
:css('vertical-align', 'middle')
:cssText(data.infoOtherParams)
:addClass(data.infoClass)
:wikitext(data.info)
-- Render the second id html.
if data.showId2 then
tablerow:tag('td')
:css('border', '0')
:css('width', data.id2Width)
:css('height', data.id2Height)
:css('background', data.id2BackgroundColor)
:css('text-align', data.id2TextAlign)
:css('font-size', data.id2FontSize)
:css('font-weight', 'bold')
:css('color', data.id2Color)
:css('padding', data.id2Padding)
:css('line-height', data.id2LineHeight)
:css('vertical-align', 'middle')
:cssText(data.id2OtherParams)
:wikitext(data.id2)
end
local title = mw.title.getCurrentTitle()
if (title.namespace == 2) and not title.text:match("/") then
return tostring(root) -- regular user page
elseif title.namespace == 14 then
return tostring(root) -- category
elseif title.isTalkPage then
return tostring(root) -- talk page
end
local legible = true
local contrast = require('Module:Color contrast')._ratio
local function has_text(wikitext)
local function get_alt(text)
return text:match("|alt=([^|]*)") or ""
end
wikitext = wikitext:gsub("]]", "|]]")
wikitext = wikitext:gsub("%[%[%s*[Mm][Ee][Dd][Ii][Aa]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ff][Ii][Ll][Ee]%s*:[^|]-(|.-)]]", get_alt)
return mw.text.trim(wikitext) ~= ""
end
if contrast { data.infoColor, data.backgroundColor, error = 0 } < 4.5 then
legible = false
end
if data.showId and contrast { data.idColor, data.idBackgroundColor, error = 0 } < 4.5 then
if has_text(data.id or "") then
legible = false
end
end
if data.showId2 and contrast { data.id2Color, data.id2BackgroundColor, error = 0 } < 4.5 then
if has_text(data.id2 or "") then
legible = false
end
end
if not legible then
root:wikitext('[[Category:可能难以辨认的用户框模板]]')
end
return tostring(root)
end
function p.categories(args, page)
-- Gets categories from [[Module:Category handler]].
-- The page parameter makes the function act as though the module was being called from that page.
-- It is included for testing purposes.
local cats = {}
cats[#cats + 1] = args.usercategory
cats[#cats + 1] = args.usercategory2
cats[#cats + 1] = args.usercategory3
if #cats > 0 then
-- Get the title object
local title
if page then
title = mw.title.new(page)
else
title = mw.title.getCurrentTitle()
end
-- Build category handler arguments.
local chargs = {}
chargs.page = page
chargs.nocat = args.nocat
chargs.main = '[[Category:未正確放置討論頁模板的頁面]]'
if args.notcatsubpages then
chargs.subpage = 'no'
end
-- User namespace.
local user = ''
for i, cat in ipairs(cats) do
user = user .. makeCat(cat)
end
chargs.user = user
-- Template namespace.
local basepage = title.baseText
local template = ''
for i, cat in ipairs(cats) do
template = template .. makeCat(cat, ' ' .. basepage)
end
chargs.template = template
return categoryHandler(chargs)
else
return nil
end
end
return p
f9c852070dccc2fa1ee92864d43a8d38cc9bfe76
Module:Lua banner
828
108
573
273
2024-08-04T14:03:26Z
黑茶
2
导入1个版本
Scribunto
text/plain
--[=[
本模块由[[Template:Lua]]调用
暂无模块调用
/****************************/
本模組由[[Template:Lua]]調用
暫無模組調用
]=]--
local yesno = require('Module:Yesno')
local mList = require('Module:List')
local mTableTools = require('Module:TableTools')
local mMessageBox = require('Module:Message box')
local p = {}
function p.main(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
return p._main(frame, args)
end
function p._main(frame, args)
local modules = mTableTools.compressSparseArray(args)
local box = p.renderBox(modules)
local trackingCategories = p.renderTrackingCategories(args, modules)
return box .. trackingCategories
end
-- if action=edit
function p.main2(frame)
local origArgs = frame:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = v:match('^%s*(.-)%s*$')
if v ~= '' then
args[k] = v
end
end
local modules = mTableTools.compressSparseArray(args)
return p.renderBox(modules)
end
--end
function p.renderBox(modules)
local boxArgs = {}
if #modules < 1 then
boxArgs.text = '<strong class="error">错误:未指定-{zh-hans:模块; zh-hant:模組;}-</strong>'
else
local moduleLinks = {}
for i, module in ipairs(modules) do
moduleLinks[i] = string.format('%s', module)
moduleLinks[i] = '[[:Module:' .. mw.title.new(moduleLinks[i]).text .. ']]'
local maybeSandbox = mw.title.new(module .. '/sandbox')
if maybeSandbox.exists then
moduleLinks[i] = moduleLinks[i] .. string.format('([[:%s|沙盒]])', maybeSandbox.fullText)
end
end
local moduleList = mList.makeList('bulleted', moduleLinks)
boxArgs.text = '此' ..
(mw.title.getCurrentTitle():inNamespaces(828,829) and '-{zh-hans:模块; zh-hant:模組;}-' or '模板') ..
'使用[[那艺娜维基:Lua|Lua语言]]:\n' .. moduleList
end
boxArgs.type = 'notice'
boxArgs.small = true
boxArgs.image = '[[File:Lua-Logo.svg|30px|alt=|link=]]'
return mMessageBox.main('mbox', boxArgs)
end
function p.renderTrackingCategories(args, modules, titleObj)
if yesno(args.nocat) then
return ''
end
local cats = {}
-- 错误分类
if #modules < 1 then
cats[#cats + 1] = '有错误的Lua模板'
end
-- Lua templates category
titleObj = titleObj or mw.title.getCurrentTitle()
local subpageBlacklist = {
doc = true,
sandbox = true,
sandbox2 = true,
testcases = true
}
if titleObj.namespace == 10
and not subpageBlacklist[titleObj.subpageText]
then
local category = args.category
if not category then
local categories = {
['Module:String'] = '使用Module:String的模板',
--['Module:Math'] = '使用LuaMath的模板',
--['Module:BaseConvert'] = '使用LuaBaseConvert的模板',
--['Module:Citation'] = '使用LuaCitation的模板'
}
categories['Module:Citation/CS1'] = categories['Module:Citation']
category = modules[1] and categories[modules[1]]
category = category or 'x'
end
cats[#cats + 1] = category
local protLevels = {
autoconfirmed = 1,
extendedconfirmed = 2,
templateeditor = 3,
sysop = 4
}
local currentProt = titleObj.protectionLevels["edit"][1]
if currentProt == nil then currentProt = 0 else currentProt = protLevels[currentProt] end
for i, module in ipairs(modules) do
if mw.title.new(module).protectionLevels["edit"] then
local moduleProt = mw.title.new(module).protectionLevels["edit"][1]
if moduleProt == nil then moduleProt = 0 else moduleProt = protLevels[moduleProt] end
if moduleProt < currentProt then
cats[#cats + 1] = "使用受保护Lua模块的模板"
break
end
end
end
end
for i, cat in ipairs(cats) do
cats[i] = string.gsub(string.format('[[Category:%s]]', cat), '%[%[Category:x%]%]', '')
end
return table.concat(cats) .. '[[Category:Lua模板]]'
end
return p
dc0cc1f5c839b737e09cd1889b2121194b550c65
Template:Doc
10
275
575
574
2024-08-04T14:03:27Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Documentation]]
{{Redirect category shell|1=
{{模板重定向}}
{{模板捷徑重定向|'''doc'''umentation|-{zh-hans:文档,文件; zh-hant:文件,文檔;}-}}
}}
1e74c7fcaac4bf434b28d16ae8810ad302871f21
Template:改进使用说明
10
276
577
576
2024-08-04T14:03:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{SAFESUBST:<noinclude />#invoke:Unsubst||date=__DATE__ |$B={{Ombox
| type = content
| name = 改进使用说明
| class = ambox-Refimprove
| image = [[File:Edit-copy green with red question mark.svg|50x40px|alt=]]
| text = 此{{#switch:{{NAMESPACE}}|Module=模块|#default=模板}}的[[Wikipedia:模板文件頁模式|文档]]'''不存在、不全面或不能详细描述其功能及/或其代码中的[[Help:模板|参数]]。'''请帮助[{{fullurl:{{FULLPAGENAME}}{{#ifexist:{{FULLPAGENAME}}/doc|/doc}}|action=edit}} 扩充并改进其文档。]{{#if:{{{talk|{{{1|}}}}}} |请参阅[[{{TALKPAGENAME}}|其讨论页]]了解详情。|}} {{#if:{{{date|{{{2|}}}}}} |{{smaller|''({{{date}}})''}}}}
}}<includeonly>{{#ifeq:{{{中文}}}|是|[[Category:可能需要翻譯使用說明的模板|{{PAGENAME}}]]|{{Dated maintenance category|||缺少或文档内容不准确的模板}}}}</includeonly>}}<noinclude>
{{Documentation}}
</noinclude>
af7b64a3cb3fe193b116044d7e46261db0179e7d
Template:缺乏使用說明
10
277
579
578
2024-08-04T14:03:28Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:改进使用说明]]
54637eee98f16dd913f0ee4edb6d5db001566d19
Module:Transclusion count/data/U
828
278
581
580
2024-08-04T14:03:29Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
["UK"] = 7000,
["UKR"] = 3900,
["URL"] = 52000,
["URS"] = 4700,
["US"] = 2900,
["USA"] = 37000,
["USSR"] = 2700,
["US_county_navigation_box"] = 50000,
["US_county_navigation_box/core"] = 50000,
["US_state_navigation_box"] = 3100,
["UTC+8"] = 2400,
["Ubl"] = 18000,
["Unblock"] = 4200,
["Unbulleted_list"] = 55000,
["Unicode"] = 5400,
["Unlink"] = 2100,
["Unping"] = 4400,
["Unreferenced"] = 65000,
["Update"] = 4800,
["Uploader_information"] = 22000,
["Url"] = 18000,
["User"] = 48000,
["User_Google"] = 2500,
["User_UTC"] = 2600,
["User_UTC+8"] = 2200,
["User_en-2"] = 2500,
["User_en-3"] = 2600,
["User_language-1"] = 5000,
["User_language-2"] = 5200,
["User_language-3"] = 4600,
["User_language-4"] = 2800,
["User_language-N"] = 9700,
["User_male"] = 2500,
["User_other"] = 9200,
["User_zh"] = 6100,
["Userbox"] = 31000,
["Userbox-2"] = 9100,
["Userbox-level"] = 3400,
["Userbox-r"] = 2100,
["Userboxbottom"] = 4300,
["Userboxtop"] = 4800,
["Userpage"] = 2700,
["Uses_Lua"] = 3000,
["Usgs-gazetteer"] = 4800,
["Module:URL"] = 84000,
["Module:Unicode_data"] = 490000,
["Module:Unicode_data/scripts"] = 55000,
["Module:Unsubst"] = 154000,
["Module:Unsubst-infobox"] = 17000,
["Module:Unsubst2"] = 4900,
["Module:Userbox"] = 32000,
["Module:Ustring"] = 48000,
}
5a8b434ed0393c9a247cb54549279bb88f201158
Template:Userbox/doc
10
279
583
582
2024-08-04T14:03:29Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{NoteTA
|G1 = IT
|G2 = MediaWiki
}}
{{內聯模板文件}}
{{Lua|Module:Userbox}}
{{高風險模板}}
{{缺乏中文說明}}
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
本模板適用於建置[[wikipedia:用戶框|用戶框]],提供使用者在用戶頁面顯示使用者的一些資訊,以免於HTML與Wikitable參數的麻煩。
'''[[WP:NFCC|合理使用圖像]]不得用於用戶框,任何使用者可在不經對方同意下,移除相關圖片。'''
== 使用方式 ==
<pre style="overflow: auto">-{}-
{{Userbox
|bodyclass = <!--自訂HTML Class參數-->
|border-c = <!--邊框色彩 (預設與 id-c 之參數相同)-->
|border-s = <!--邊框像素大小 (預設值:1)-->
|float = <!--流動對齊方式 left|right|none (預設值:left)-->
|id = <!--id 圖片或文字(選用,預設尺寸是x45px)-->
|id-a = <!--id 水平對齊方式 left/center/right/justify (預設:center)-->
|id-c = <!--id 的背景色彩 (預設:#d0d0d0)-->
|id-fc = <!--id 的文字色彩 (預設:black)-->
|id-h = <!--id 框的像素大小 (預設:45)-->
|id-lh = <!--id 行高 (預設:1em)-->
|id-op = <!--id 的其他 CSS 參數-->
|id-p = <!--id 的儲存格留白值 (預設:0 1px 0 0)-->
|id-s = <!--id 文字點數 (預設:14)-->
|id-w = <!--id 框長度 (預設:45)-->
|info-class = <!--Adds an HTML class attribute to the "info" HTML table-row, to allow for styling, emission of microformats, etc.-->
|info = <!--info 框圖文內容-->
|info-a = <!--info 框水平對齊方式 left/center/right/justify (預設:left)-->
|info-c = <!--info 框背景色 (預設:#e0e0e0)-->
|info-fc = <!--info 框文字色彩 (預設:black)-->
|info-lh = <!--info 框行高 (預設:1.25em)-->
|info-op = <!--info 框的其他CSS樣式參數-->
|info-p = <!--info 框的留白值 (預設:0 4px 0 4px)-->
|info-s = <!--info 文字點數 (預設:8)-->
|nocat = <!--屏蔽頁面分類 (預設:false)-->
|usercategory = <!--使用者自設分類(選用)-->
|usercategory2 = <!--使用者自設分類(選用)-->
|usercategory3 = <!--使用者自設分類(選用)-->
}}
</pre>
* 全部參數皆為選填
* 圖像建議少於45px
<!-- explain what this template's parameters do -- if no params, delete the definition -->
多数基于HTML的表格仅用这些参数的一小部分。以下子集可以用来把HTML用户框快速转换成这里所用的格式:
<pre>
{{Userbox
|border-c =
|id =
|id-c =
|id-fc =
|id-s =
|info =
|info-c =
|info-fc =
|info-lh =
|info-s =
|nocat = {{{nocat|}}}
|usercategory =
}}
</pre>
== 範例 ==
{|
!style="width: 300px;"| 代码
!效果
|-
| <pre>{{Userbox}}</pre> || {{Userbox}}
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 2
|id = foo
|id-c = #ffffee
|id-s = 20
|info = ''foo bar''
|info-c = #ffeeff
|info-s = 12
}}</pre> || {{Userbox|id=foo|id-s=20|id-c=#ffffee|info=''foo bar''|info-c=#ffeeff|info-s=12|border-c=#aaffaa|border-s=2}}
|-
| colspan="2"| 以下展示高度超过45px的用户框的默认外观,比较一下上下两个用户框的差异。
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 2
|id = foo logo
|id-c = #ffffee
|info = ''We are trying to see
default distance in between text
lines, see the distance in
between cell content and its border,
and also see total height.''
|info-c = #ffeeff
}}</pre> || {{Userbox|id=foo logo|id-c=#ffffee|info=''We are trying to see default distance in between text lines, see the distance in between cell content and its border, and also see total height.''|info-c=#ffeeff|border-c=#aaffaa|border-s=2}}
|-
| colspan="2"| 以下展示怎样能修改用户框并进一步指定参数来降低用户框的高度以达到推荐的45px,即使有四行文字。在四行文字之下,单元格边距参数info-p也可以设置成1pt 1pt 1pt 2pt,或者1pt 2pt以达到更好的效果。
|-
| <pre>{{Userbox
|border-c = #aaffaa
|border-s = 1
|id = foo logo
|id-c = #ffffee
|id-lh = 1.1em
|id-s = 14
|info = ''We have specified values
to lessen the distance in between
text lines & padding space in between
cell content and its border.''
|info-c = #ffeeff
|info-lh = 1.05em
|info-p = 1pt
|info-s = 8
}}</pre> || {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffffee|info=''We have specified values to lessen the distance in between text lines & padding space in between cell content and its border.''|info-c=#ffeeff|info-s=8|info-p=1pt|info-lh=1.05em|border-c=#aaffaa|border-s=1}}
|-
| colspan="2"| 以下针对高级用户,展示怎样指定其他[[CSS]]属性,例如,font-family调整字体,text-align从默认参数调整对齐方式。如下所示,右边是2个用户框:上面一个是不带font-family或text-align参数;下面一个是以填写info-op参数来使用此类代码显示的。
|-
| <pre>{{Userbox
|border-c = #afa
|border-s = 2
|id = foo logo
|id-c = #ffe
|id-lh = 1.1em
|id-s = 14
|info = foo bar
|info-c = #fef
|info-op = font-family:'Courier New'; text-align:center;
|info-s = 14
}}</pre> || colspan="2"| {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffe|info=foo bar|info-c=#fef|info-s=14|border-c=#afa|border-s=2}} <br style="clear:both"> <br /> {{Userbox|id=foo logo|id-s=14|id-lh=1.1em|id-c=#ffe|info=foo bar|info-c=#fef|info-s=14|info-op=font-family:'Courier New'; text-align:center;|border-c=#afa|border-s=2}}
|}<!-- customize if needed to illustrate parameter use -->
== 模板数据 ==
{{TemplateDataHeader}}
<templatedata>
{
"description": "本模板適用於建置用戶框,提供使用者在用戶頁面顯示使用者的一些資訊,以免於HTML與Wikitable參數的麻煩。",
"params": {
"bodyclass": {
"label": "bodyclass",
"description": "自訂HTML Class參數",
"type": "string",
"default": "id-c"
},
"border-c": {
"label": "border-c",
"description": "邊框色彩",
"type": "string"
},
"border-s": {
"label": "border-s",
"description": "邊框像素大小",
"type": "string",
"default": "1"
},
"float": {
"label": "float",
"description": "流動對齊方式 left|right|none",
"type": "string",
"default": "left"
},
"id": {
"label": "id",
"description": "id 圖片或文字(選用)",
"type": "string",
"default": "x45px"
},
"id-a": {
"label": "id-a",
"description": "id 水平對齊方式 left/center/right/justify",
"type": "string",
"default": "center"
},
"id-c": {
"label": "id-c",
"description": "id 的背景色彩",
"type": "string",
"default": "#d0d0d0"
},
"id-fc": {
"label": "id-fc",
"description": "id 的文字色彩",
"type": "string",
"default": "black"
},
"id-h": {
"label": "id-h",
"description": "id 框的像素大小",
"type": "string",
"default": "45"
},
"id-lh": {
"label": "id-lh",
"description": "id 行高",
"type": "string",
"default": "1em"
},
"id-op": {
"label": "id-op",
"description": "id 的其他 CSS 參數",
"type": "string"
},
"id-p": {
"label": "id-p",
"description": "id 的儲存格留白值",
"type": "string",
"default": "0 1px 0 0"
},
"id-s": {
"label": "id-s",
"description": "id 文字點數",
"type": "string",
"default": "14"
},
"id-w": {
"label": "id-w",
"description": "id 框長度,單位是像素",
"type": "string",
"default": "45"
},
"info-class": {
"label": "info-class",
"description": "Adds an HTML class attribute to the “info” HTML table-row, to allow for styling, emission of microformats, etc.",
"type": "string"
},
"info": {
"label": "info",
"description": "info 框圖文內容",
"type": "string"
},
"info-a": {
"label": "info-a",
"description": "info 框水平對齊方式 left/center/right/justify",
"type": "string",
"default": "left"
},
"info-c": {
"label": "info-c",
"description": "info 框背景色",
"type": "string",
"default": "#e0e0e0"
},
"info-fc": {
"label": "info-fc",
"description": "info 框文字色彩",
"type": "string",
"default": "black"
},
"info-lh": {
"label": "info-lh",
"description": "info 框行高",
"type": "string",
"default": "1.25em"
},
"info-op": {
"label": "info-op",
"description": "info 框的其他CSS樣式參數",
"type": "string"
},
"info-p": {
"label": "info-p",
"description": "info 框的留白值",
"type": "string",
"default": "0 4px 0 4px"
},
"info-s": {
"label": "info-s",
"description": "info 文字點數",
"type": "string",
"default": "8"
},
"nocat": {
"label": "nocat",
"description": "屏蔽頁面分類",
"type": "string",
"default": "false"
},
"usercategory": {
"label": "usercategory",
"description": "使用者自設分類(選用)",
"type": "string"
},
"usercategory2": {
"label": "usercategory2",
"description": "使用者自設分類(選用)",
"type": "string"
},
"usercategory3": {
"label": "usercategory3",
"description": "使用者自設分類(選用)",
"type": "string"
}
}
}
</templatedata>
== 重定向 ==
* {{tl|用户框}}:中文名重定向。
* {{tl|User box}}、{{tl|User Box}}:为便于在{{tl|Userboxes}}中引用而创建的重定向。
== 参见 ==
* [[维基百科:用户框]]
* {{Tlx|Userbox-2}}:左右两边都有id区的用户框。
* {{Tlx|Userbox-r}}:右边有id区的用户框。
* {{Tlx|Userbox-m}}:只有id区的用户框。
* [[网页颜色]]
==微格式==
;bodyclass : This parameter is inserted into the "class" attribute for the userbox as a whole.
;info-class : This parameter is inserted into the "class" attribute for the info component.
{{请求翻译句|This template supports the addition of [[microformat]] information.}} This is done by adding "class" attributes to various data cells, indicating what kind of information is contained within. To flag a userbox as containing [[hCard]] information about a person, for example, add the following parameter:
<pre>
|bodyclass = vcard
</pre>
''or''
<pre>
|info-class = vcard
</pre>
''then'' (for example):
<pre>
|title = ... the books of <span class="fn">[[Iain Banks]]</span>
</pre>
... and so forth.
Examples include:
* [[:en:User:UBX/Iain Banks]] - person
* [[:en:Template:User Microformats]] - group (WikiProject Microformats)
* [[:en:Template:User Brum]] - place (Birmingham)
有關微格式的參數設置,請參考[[Wikipedia:專題/微格式|微格式專題]]。
<includeonly>{{sandbox other||
<!-- 本行下加入模板的分類,跨維基連結加入Wikidata(參見[[Wikipedia:Wikidata]]) -->
[[Category:元用户框模板| ]]
}}</includeonly>
55c658a741bc9a58a5008bd0e1cd1cbaeee5b872
Template:缺乏中文說明
10
280
585
584
2024-08-04T14:03:29Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{缺乏使用說明|中文=是}}<noinclude>{{Documentation}}[[Category:模板页的模板]]</noinclude>
4701f009a3627981bfadd1e70c2ec749724b8c65
Template:請求翻譯句
10
281
587
586
2024-08-04T14:03:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{{1|<noinclude>+</noinclude>}}}|<mark class="template-facttext" title="需要{{#if:{{{lang|+}}}|從{{ISO 639 name|{{{lang|en}}}}}}}翻譯為中文">{{{1<noinclude>|This is an untranslated statement.</noinclude>}}}</mark>|}}{{fix
|link=Wikipedia:翻譯請求
|title=需要{{#if:{{{lang|+}}}|從{{ISO 639 name|{{{lang|en}}}}}}}翻譯為中文
|text=翻譯請求
|class = noprint Template-Fact
}}{{namespace detect
| main = [[Category:正在翻譯的條目]]{{#if:{{{date|}}}|[[Category:自{{{date}}}正在翻譯的條目]]}}
| template = [[Category:正在翻譯的模板]]
| wikipedia = [[Category:正在翻譯的維基百科頁面]]
| help = [[Category:正在翻譯的維基百科頁面]]
| other = }}<noinclude>{{documentation}}</noinclude>
67fd36bec687174cab506fe70201154767ca0149
Template:內聯模板文件
10
282
589
588
2024-08-04T14:03:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向 [[Template:Documentation_subpage]]
{{別名重定向}}{{模板重定向}}
1528d83c7e5427f26645681e049a0887baf9d260
Template:高風險模板
10
283
591
590
2024-08-04T14:03:30Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#重定向[[Template:High-use]]
2addfe7d74d1f617ed20992212229200d0866fd6
Template:User 大贝塔
10
284
592
2024-08-04T14:11:23Z
黑茶
2
创建页面,内容为“ {{Userbox |border-c = black |border-s = 1 |id = 大贝塔 |id-c = gray |info = 这个用户喜欢听'''[[那艺娜]]'''的'''[[大贝塔]]'''。 |info-c = gray |info-s = 9 }}”
wikitext
text/x-wiki
{{Userbox
|border-c = black
|border-s = 1
|id = 大贝塔
|id-c = gray
|info = 这个用户喜欢听'''[[那艺娜]]'''的'''[[大贝塔]]'''。
|info-c = gray
|info-s = 9
}}
8b18f1dcc3ec3a9e757b1ab9f083bab8550a1250
Userboxbottom
0
285
594
593
2024-08-04T14:12:53Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>
|}</includeonly><noinclude>{{Documentation}}
</noinclude>
b333f86f0f9f9c041965fdf594b197311bb4b36c
Userboxtop
0
286
596
595
2024-08-04T14:12:54Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{|name="userboxes" id="userboxes" style="margin-left: 0em; margin-right: 0em; margin-bottom: 0.5em; width: {{{width|248}}}px; border: {{{bordercolor|#99B3FF}}} solid 1px; background-color: {{{backgroundcolor|var(--background-color-base,#FFFFFF)}}}; color: {{{textcolor|var(--color-emphasized,#000000)}}}; float: {{{2|{{{align|right}}}}}}; {{{extra-css|}}}" class="vcard userboxes {{{extra-class|}}}"
|<div style="text-align: center; font-size: 120%; font-weight: bold;">{{{1|{{{toptext|<div class="fn">{{BASEPAGENAME}}</div>的[[Wikipedia:用戶框|用戶框]]}}}}}}</div><noinclude>
|}{{Documentation}}
</noinclude>
b653aebf2eda0153ba8eb482c67102d55cec15a3
Tl
0
287
598
597
2024-08-04T14:12:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{[[{{transclude|{{{1}}}}}|{{{1}}}]]{{#if:{{{2|{{{arg|}}}}}}|{{!}}{{{2|{{{arg}}}}}}}}}}</includeonly><noinclude>
{{Documentation}}
<!-- 請在將分類與跨語言連結增加在 /doc 子頁面 -->
</noinclude>
db73d4542a3c4808bbcbc2708c654b3bc0834fba
Transclude
0
288
600
599
2024-08-04T14:12:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch: {{NAMESPACE: {{{1}}} }}
|#default = {{FULLPAGENAME: {{{1}}} }} <!-- eg "User:Foo" -->
|{{ns:0}} =
{{#ifeq: {{NAMESPACE: {{{1}}} }} | {{NAMESPACE: Template{{{1}}} }}
| Template:{{{1}}} <!-- no leading colon, eg "Foo" -->
| {{PAGENAME: {{{1}}} }} <!-- leading colon, eg ":Foo", so we want the article -->
}}
}}<noinclude>
{{documentation}}
</noinclude>
d0239e71e5745cd0d4efd032cee07341e111376b
Documentation
0
289
602
601
2024-08-04T14:12:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#invoke:documentation|main|_content={{ {{#invoke:documentation|contentTitle}}}}}}
cc4eb5999a198597c14b859d18d2aa7b190e3af0
Userboxbottom/doc
0
290
604
603
2024-08-04T14:13:01Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
收尾{{tl|Userboxtop}}之參數模板。
== 使用方法 ==
參閱{{tl|Userboxtop}}與{{tl|Userboxbreak}}的語法範例。
== 注意事项 ==
本模板並非空白。
== 參見 ==
*[[Template:Userboxtop]]
*[[Template:Userboxbreak]]
==重定向==
* {{tl|Boxboxbottom}} 重定向至此。
* {{tl|Userboxbot}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
0592e0bd8558911d64b9785eefecf681129bac45
Tlx
0
291
606
605
2024-08-04T14:13:01Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><!--
--><code><!--
--><nowiki>{{</nowiki>{{#if:{{{subst|}}} |[[Help:替换引用|subst]]:}}<!--
-->[[{{{LANG|}}}{{{SISTER|}}}{{ns:Template}}:{{{1|}}}|{{{1|}}}]]<!--
-->{{#if:{{{2|}}} ||{{{2}}}}}<!--
-->{{#if:{{{3|}}} ||{{{3}}}}}<!--
-->{{#if:{{{4|}}} ||{{{4}}}}}<!--
-->{{#if:{{{5|}}} ||{{{5}}}}}<!--
-->{{#if:{{{6|}}} ||{{{6}}}}}<!--
-->{{#if:{{{7|}}} ||{{{7}}}}}<!--
-->{{#if:{{{8|}}} ||{{{8}}}}}<!--
-->{{#if:{{{9|}}} ||{{{9}}}}}<!--
-->{{#if:{{{10|}}} ||{{{10}}}}}<!--
-->{{#if:{{{11|}}} ||{{{11}}}}}<!--
-->{{#if:{{{12|}}} ||{{{12}}}}}<!--
-->{{#if:{{{13|}}} ||{{{13}}}}}<!--
-->{{#if:{{{14|}}} ||{{{14}}}}}<!--
-->{{#if:{{{15|}}} ||{{{15}}}}}<!--
-->{{#if:{{{16|}}} ||{{{16}}}}}<!--
-->{{#if:{{{17|}}} ||{{{17}}}}}<!--
-->{{#if:{{{18|}}} ||{{{18}}}}}<!--
-->{{#if:{{{19|}}} ||{{{19}}}}}<!--
-->{{#if:{{{20|}}} ||{{{20}}}}}<!--
-->{{#if:{{{21|}}} ||''...''}}<!--
--><nowiki>}}</nowiki><!--
--></code><!--
--></includeonly><noinclude>
{{Documentation}}</noinclude>
d8d004509af027beddd80b75c1e20c88dfabbc76
Flatlist
0
292
608
607
2024-08-04T14:13:02Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="hlist {{{class|}}}" style="margin-left: {{#expr:{{{indent|0}}}*1.6}}em; {{{style|}}}">{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
be7fa9dab626ef8ba526d6033ec3bc056ab5ff2d
Sandbox other
0
293
610
609
2024-08-04T14:13:02Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{#ifeq:{{SUBPAGENAME}}|sandbox|1}}{{#invoke:String|match|{{PAGENAME}}|/sandbox/styles.css$|plain=false|nomatch=}}|{{{1|}}}|{{{2|}}}}}<!--
--><noinclude>{{documentation}}</noinclude>
3462b190d62e7d7ed1a408cd5607c5c124a1ce15
Endflatlist
0
294
612
611
2024-08-04T14:13:02Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
</div><noinclude>
{{documentation|Template:Flatlist/doc}}
</noinclude>
8664fe211feb15b6d1b29c9f1b83dccc0cabbb5a
UF-hcard-part
0
295
614
613
2024-08-04T14:13:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
本模板使用了[[HCard|hCard微格式]]標記,被標記的人物或地點資料可以被電腦分析讀取,以便将其自動归類,或者-{zh-hans:通过; zh-hant:透過}-專門的瀏覽器取得資料訊息,例如將訊息加入通訊錄。關於在維基百科使用微格式的詳細訊息,請參見[[WikiProject:微格式|微格式維基專題]]。
出生日期(''bday'')參數只能使用於包含了 {{tl|bd}} 或 {{tl|Birth date and age}} 模板的信息框。
{{flatlist}}
*adr
*bday
*county-name
*'''fn(必須)'''
*geo
*honorific-prefix
*honorific-suffix
*label
*locality
*nickname
*note
*org
*role
*vcard
{{endflatlist}}
'''請不要移除或重新命名這些class。'''
<includeonly>{{sandbox other||
[[Category:使用hCard的模板|{{PAGENAME}}]]
}}</includeonly><noinclude>
{{Documentation |content={{Microformat message templates|state=expanded}}}}
[[Category:微格式信息模板]]
[[Category:使用hCard的模板| ]]
</noinclude>
a31db00f7dbc6e078b4d4ca6fc18dce8c833d4f2
Userboxtop/doc
0
296
616
615
2024-08-04T14:13:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
這個模板可以將好幾個用戶框和其連帶的圖片整理收集為一個整齊的區塊。
過去有[[Wikipedia:什么是条目|條目]]使用此模板,但現今條目'''不應'''再使用此模板。若條目確有內容需要框住,請使用{{tlx|Stack}}模板。
== 使用方法 ==
<pre><nowiki>{{userboxtop
| align =
| backgroundcolor =
| bordercolor =
| extra-css =
| textcolor =
| toptext =
| width =
}}
[userboxes]
{{userboxbottom}}</nowiki></pre>
所有參數都是'''選擇性的'''。
{{UF-hcard-part}}
===個人化===
以下有一些詳細介紹
{| class="wikitable"
|-
! 參數
! 數值範圍
|-
| <code>align</code>
| <code>left</code>, <code>center</code>, 或<code>right</code>(預設值)
|-
| <code>backgroundcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#FFFFFF</tt>。
|-
| <code>bordercolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#99B3FF</tt>。
|-
| <code>extra-css</code>
| 可使用額外[[Cascading Style Sheets|CSS]]資訊。
|-
| <code>textcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#000000</tt>。
|-
| <code>toptext</code>
| 取代預設的{{tl|Userboxes}}文字和链接。可包含wiki-markup。
|-
| <code>width</code>
| 調整用戶框的闊度(預設為248px)。
|}
中間可插入新行以及重組分類。詳情可參看{{tl|Userboxbreak}}。
==隱藏用戶框==
你可以隱藏用了這個模板的用戶框。只需在你的個人CSS頁(如果你的外觀設定爲Monobook,就是[[Special:Mypage/monobook.css|monobook.css]],其他外觀同理) 中加入<code><nowiki>.userboxes { display: none; }</nowiki></code>即可。
== 參見 ==
*[[Template:Userboxbottom]]
*[[Template:Userboxbreak]]
* [[Template:Userbox encouragement container]](将维基荣誉模板美观的收纳到用户框)
== 重定向 ==
*{{tl|Boxboxtop}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
1fc7601b7c6ffdedcd77767760003f4141bac9e5
Template:Userboxbottom
10
297
618
617
2024-08-04T14:15:23Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>
|}</includeonly><noinclude>{{Documentation}}
</noinclude>
b333f86f0f9f9c041965fdf594b197311bb4b36c
Template:Userboxtop
10
298
620
619
2024-08-04T14:15:23Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{|name="userboxes" id="userboxes" style="margin-left: 0em; margin-right: 0em; margin-bottom: 0.5em; width: {{{width|248}}}px; border: {{{bordercolor|#99B3FF}}} solid 1px; background-color: {{{backgroundcolor|var(--background-color-base,#FFFFFF)}}}; color: {{{textcolor|var(--color-emphasized,#000000)}}}; float: {{{2|{{{align|right}}}}}}; {{{extra-css|}}}" class="vcard userboxes {{{extra-class|}}}"
|<div style="text-align: center; font-size: 120%; font-weight: bold;">{{{1|{{{toptext|<div class="fn">{{BASEPAGENAME}}</div>的[[Wikipedia:用戶框|用戶框]]}}}}}}</div><noinclude>
|}{{Documentation}}
</noinclude>
b653aebf2eda0153ba8eb482c67102d55cec15a3
Template:Userboxbottom/doc
10
299
622
621
2024-08-04T14:15:31Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
== 模板介紹 ==
收尾{{tl|Userboxtop}}之參數模板。
== 使用方法 ==
參閱{{tl|Userboxtop}}與{{tl|Userboxbreak}}的語法範例。
== 注意事项 ==
本模板並非空白。
== 參見 ==
*[[Template:Userboxtop]]
*[[Template:Userboxbreak]]
==重定向==
* {{tl|Boxboxbottom}} 重定向至此。
* {{tl|Userboxbot}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
0592e0bd8558911d64b9785eefecf681129bac45
Template:Flatlist
10
300
624
623
2024-08-04T14:15:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="hlist {{{class|}}}" style="margin-left: {{#expr:{{{indent|0}}}*1.6}}em; {{{style|}}}">{{#if:{{{1|}}}|
{{{1}}}
</div>}}<noinclude></div>
{{documentation}}
</noinclude>
be7fa9dab626ef8ba526d6033ec3bc056ab5ff2d
Template:Endflatlist
10
301
626
625
2024-08-04T14:15:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
</div><noinclude>
{{documentation|Template:Flatlist/doc}}
</noinclude>
8664fe211feb15b6d1b29c9f1b83dccc0cabbb5a
Template:UF-hcard-part
10
302
628
627
2024-08-04T14:15:32Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
本模板使用了[[HCard|hCard微格式]]標記,被標記的人物或地點資料可以被電腦分析讀取,以便将其自動归類,或者-{zh-hans:通过; zh-hant:透過}-專門的瀏覽器取得資料訊息,例如將訊息加入通訊錄。關於在維基百科使用微格式的詳細訊息,請參見[[WikiProject:微格式|微格式維基專題]]。
出生日期(''bday'')參數只能使用於包含了 {{tl|bd}} 或 {{tl|Birth date and age}} 模板的信息框。
{{flatlist}}
*adr
*bday
*county-name
*'''fn(必須)'''
*geo
*honorific-prefix
*honorific-suffix
*label
*locality
*nickname
*note
*org
*role
*vcard
{{endflatlist}}
'''請不要移除或重新命名這些class。'''
<includeonly>{{sandbox other||
[[Category:使用hCard的模板|{{PAGENAME}}]]
}}</includeonly><noinclude>
{{Documentation |content={{Microformat message templates|state=expanded}}}}
[[Category:微格式信息模板]]
[[Category:使用hCard的模板| ]]
</noinclude>
a31db00f7dbc6e078b4d4ca6fc18dce8c833d4f2
Template:Userboxtop/doc
10
303
630
629
2024-08-04T14:15:33Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{template doc page viewed directly}}</noinclude>
<!-- 在本行下編輯模板說明 -->
這個模板可以將好幾個用戶框和其連帶的圖片整理收集為一個整齊的區塊。
過去有[[Wikipedia:什么是条目|條目]]使用此模板,但現今條目'''不應'''再使用此模板。若條目確有內容需要框住,請使用{{tlx|Stack}}模板。
== 使用方法 ==
<pre><nowiki>{{userboxtop
| align =
| backgroundcolor =
| bordercolor =
| extra-css =
| textcolor =
| toptext =
| width =
}}
[userboxes]
{{userboxbottom}}</nowiki></pre>
所有參數都是'''選擇性的'''。
{{UF-hcard-part}}
===個人化===
以下有一些詳細介紹
{| class="wikitable"
|-
! 參數
! 數值範圍
|-
| <code>align</code>
| <code>left</code>, <code>center</code>, 或<code>right</code>(預設值)
|-
| <code>backgroundcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#FFFFFF</tt>。
|-
| <code>bordercolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#99B3FF</tt>。
|-
| <code>extra-css</code>
| 可使用額外[[Cascading Style Sheets|CSS]]資訊。
|-
| <code>textcolor</code>
| 任何 [[網頁顏色模式|網頁顏色]](名稱或<tt>#XXXXXX</tt>格式)。預設值為<tt>#000000</tt>。
|-
| <code>toptext</code>
| 取代預設的{{tl|Userboxes}}文字和链接。可包含wiki-markup。
|-
| <code>width</code>
| 調整用戶框的闊度(預設為248px)。
|}
中間可插入新行以及重組分類。詳情可參看{{tl|Userboxbreak}}。
==隱藏用戶框==
你可以隱藏用了這個模板的用戶框。只需在你的個人CSS頁(如果你的外觀設定爲Monobook,就是[[Special:Mypage/monobook.css|monobook.css]],其他外觀同理) 中加入<code><nowiki>.userboxes { display: none; }</nowiki></code>即可。
== 參見 ==
*[[Template:Userboxbottom]]
*[[Template:Userboxbreak]]
* [[Template:Userbox encouragement container]](将维基荣誉模板美观的收纳到用户框)
== 重定向 ==
*{{tl|Boxboxtop}} 重定向至此。
<includeonly>
<!-- 本行下加入模板的分類 -->
[[Category:用户框模板]]
</includeonly>
1fc7601b7c6ffdedcd77767760003f4141bac9e5
User:黑茶
2
304
631
2024-08-04T14:18:15Z
黑茶
2
创建页面,内容为“{{Userboxbottom}} {{User 大贝塔}} {{Userboxtop}}”
wikitext
text/x-wiki
{{Userboxbottom}}
{{User 大贝塔}}
{{Userboxtop}}
653418118695ec3315207b638a51bd26d6562304
634
631
2024-08-05T06:33:19Z
黑茶
2
wikitext
text/x-wiki
{{Userboxtop}}
{{User 大贝塔}}
{{Userboxbottom}}
c981217ba3d2c8ff619fa199abbeae414d96ac9f
首页
0
1
632
8
2024-08-05T04:48:37Z
黑茶
2
页面内容被替换为“__NOTOC__ == 欢迎来到 {{SITENAME}}! == 欢迎来到[[那艺娜]]维基”
wikitext
text/x-wiki
__NOTOC__
== 欢迎来到 {{SITENAME}}! ==
欢迎来到[[那艺娜]]维基
f18e82131e68910fb4bb2a16939e58bc76cd08d9
那艺娜
0
171
633
539
2024-08-05T04:56:34Z
黑茶
2
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 参考资料 ==
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈]]
82729c2d6b2e6e28045c7d9b1caef0d514708734
686
633
2024-08-14T11:29:55Z
黑茶
2
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 发行歌曲 ==
* 《大贝塔》
== 参考资料 ==
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈]]
f1a5f25a2cbbd9b1944965a43b8a0bb8a04aec04
687
686
2024-08-18T03:56:07Z
黑茶
2
wikitext
text/x-wiki
__INDEX__
<languages/>
<translate>
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 发行歌曲 ==
* 《大贝塔》
== 参考资料 ==
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈]]
</translate>
a5ef736a5563ca0aa7d1534daa0487413d724f96
688
687
2024-08-18T04:02:09Z
黑茶
2
准备翻译的页面
wikitext
text/x-wiki
__INDEX__
<languages/>
<translate>
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
== 发展历程 ==
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 发行歌曲 ==
* 《大贝塔》
== 参考资料 ==
</translate>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<translate>
</translate>
2d5d1e7f9d7be57145e2ee113ff9af8c2dae4a75
689
688
2024-08-18T04:04:02Z
黑茶
2
标记此版本进行翻译
wikitext
text/x-wiki
__INDEX__
<languages/>
<translate>
<!--T:1-->
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
<!--T:2-->
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
== 发展历程 == <!--T:3-->
<!--T:4-->
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
<!--T:5-->
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
<!--T:6-->
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
== 发行歌曲 == <!--T:7-->
<!--T:8-->
* 《大贝塔》
== 参考资料 == <!--T:9-->
</translate>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<translate>
<!--T:10-->
</translate>
9facf285195d0c1cfcc36c14acdcbbfad8c6d333
Template:每日一句
10
305
636
635
2024-08-05T14:52:51Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<div class="boilerplate metadata" align="center" style="border-top: 2px solid #3030FF; margin: 0 0 1em 0; border-bottom: 2px solid #3030FF; border-right: 2px solid #3030FF; margin: 0 0 1em 0; border-left: 2px solid #3030FF; padding: 5px 5px 5px 5px">
'''每日一句'''
<div style="max-height:240px;overflow:auto">
{{#invoke:Rand|randitem|{{每日一句/投稿}}}}</div><div class="center><span style="font-size:small;"><span class="mw-ui-button";style="text-color:white"><span class="plainlinks">{{purge|換一個}}</span></span> <span class="mw-ui-button";style="text-color:white">[[Template:每日一句/投稿|說一句]]</span></span></div></div><noinclude>
{{doc}}
[[Category:用戶頁模板|O]]
[[Category:維基百科幽默模板]]
</noinclude>
31728191bff7e1db5157e1b4bd2a8c68858c82ad
Template:Tsl
10
306
638
637
2024-08-05T14:52:55Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Translink]]
{{縮寫重定向}}
{{模板重定向}}
f4c0065c4503db756be96de5c746c28184cf9f1a
Template:Translink
10
307
640
639
2024-08-05T14:52:55Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh |main |lang-code={{{1}}} |1={{#if:{{{3|}}}|{{{3}}}|{{{2}}}}} |2={{{2|}}} |d={{{4|}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation}}</noinclude>
5bdf50d43763a30c17c72549cf86b4548c13651a
Template:Link-en
10
308
642
641
2024-08-05T14:52:55Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/en]]
{{短名重定向}}
{{模板重定向}}
866c4d05848633090eb9763d9c480ebe2c6b4fdf
Template:Internal link helper/en
10
309
644
643
2024-08-05T14:52:56Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=en |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>
{{Documentation|Template:Internal link helper/doc}}
</noinclude>
8879dbc293b7701b98990406b06eb03f75ed837e
Module:Ilh
828
310
646
645
2024-08-05T14:52:56Z
黑茶
2
导入1个版本
Scribunto
text/plain
local ilh = {}
local getArgs
local yesno = require('Module:Yesno')
local lan = require('Module:Lan')
local langData = mw.loadData( 'Module:Ilh/data' )
--local frameArgs
local COMMON_TAIL='</span>'
local MODEL={
frame_head='<span class="ilh-all %s" data-orig-title="%s" data-lang-code="%s" data-lang-name="%s" data-foreign-title="%s">'
,frame_tail=COMMON_TAIL
,page_head='<span class="ilh-page">'
,page_tail=COMMON_TAIL
,comment_head='<span class="noprint ilh-comment">('
,comment_tail=')'..COMMON_TAIL
,lang_head='<span class="ilh-lang">'
,lang_tail=COMMON_TAIL
,colon='<span class="ilh-colon">:</span>'
,link_head='<span class="ilh-link">'
,link_body='-{[[:%s:%s|<span lang="%s" dir="auto">%s</span>]]}-'
,link_tail=COMMON_TAIL
}
local clazz_pageExist_framehead='ilh-blue'
local TRA_CAT='[[Category:有蓝链却未移除内部链接助手模板的页面]]'
function ilh.main(frame)
if not getArgs then
getArgs = require('Module:Arguments').getArgs
end
local args = getArgs(frame)
if langData[args['lang-code']] == nil then
args['lang'] = mw.language.fetchLanguageName( args['lang-code'], mw.getContentLanguage():getCode() )
elseif langData[args['lang-code']]['lang-hans'] and langData[args['lang-code']]['lang-hans'] then
args['lang'] = lan._main({['zh-hans']=langData[args['lang-code']]['lang-hans'], ['zh-hant']=langData[args['lang-code']]['lang-hant']}, frame)
elseif langData[args['lang-code']]['lang'] == nil then
args['lang'] = mw.language.fetchLanguageName( args['lang-code'], mw.getContentLanguage():getCode() )
else
args['lang'] = langData[args['lang-code']]['lang']
end
return ilh._ilh(args)
end
function ilh._ilh(args)
--frameArgs = getArgs(frame, {frameOnly=true})
local context={}
context["isMainPage"]=ilh.isMainPage()
context["localPage"]=args[1]
context["foreignPage"]=args[2] or args[1] --如果{{{2}}}不传入的话
context["displayName"]=args["d"] or args[1]
context["langCode"]=args["lang-code"]
context["lang"]=args["lang"]
context["nocat"]=yesno( args["nocat"] , false )
context["isExist"]= (args["$exist$"] and args["$exist$"]==1) or ilh.isExist(context["localPage"])
local curPage_obj=mw.title.getCurrentTitle()
context["isNoCatWithNamespace"]=curPage_obj:inNamespaces(2,828) --User,Module
--context["curPageNamespace"]=curPage_obj.namespace
return (context["isMainPage"] and ilh.onlyLink(context)) or ilh.functionLink(context)
end
function ilh.onlyLink(context)
return ( context["isExist"] and mw.ustring.format( '[[%s|%s]]', context["localPage"], context["displayName"] ) ) or context["displayName"]
end
function ilh.functionLink(context)
context["_localPage"]=mw.ustring.gsub(context["localPage"],'"','"')
context["_foreignPage"]=mw.ustring.gsub(context["foreignPage"],'"','"')
local need_cat=
(not context["nocat"])
and
(not context["isNoCatWithNamespace"])
--[[not (
context["curPageNamespace"]==2 --User
or context["curPageNamespace"]==828 --Module
)]]
--mw.log(context["nocat"])
--mw.log(context["curPageNamespace"])
--mw.log(need_cat)
local output_context={}
table.insert(output_context,
mw.ustring.format(MODEL.frame_head ,
(context["isExist"] and clazz_pageExist_framehead) or ''
,context["_localPage"]
,context["langCode"]
,context["lang"]
,context["_foreignPage"]
)
)
table.insert(output_context,MODEL.page_head)
table.insert(output_context,
mw.ustring.format('[[:%s|%s]]' ,
context["localPage"],context["displayName"]
)
)
table.insert(output_context,MODEL.page_tail)
if context["isExist"] then
if need_cat then
table.insert(output_context,TRA_CAT)
end
else
table.insert(output_context,MODEL.comment_head)
table.insert(output_context,MODEL.lang_head)
table.insert(output_context,context["lang"])
table.insert(output_context,MODEL.lang_tail)
table.insert(output_context,MODEL.colon)
table.insert(output_context,MODEL.link_head)
table.insert(output_context,
mw.ustring.format(MODEL.link_body,
context["langCode"]
,(context["foreignPage"] or context["localPage"])
,context["langCode"]
,(context["foreignPage"] or context["localPage"])
)
)
table.insert(output_context,MODEL.link_tail)
table.insert(output_context,MODEL.comment_tail)
end
table.insert(output_context,MODEL.frame_tail)
return table.concat(output_context,"")
end
--以下需要更高效的实现
--确定主页
--使用mw信息获得主页名
--使用language库获得本站默认语言代码(zh)来确定信息的对应语言,获得全主页名
---因为其他zh分语言只有名,没有命名空间,可以识别出来,但麻烦
--然后判断当前页和主页是否一致
---计划做重定向判断,但没需要
function ilh.isMainPage()
local mainpage_msgobj=mw.message.new('Mainpage')
mainpage_msgobj=mainpage_msgobj:inLanguage(mw.getContentLanguage():getCode())
local mainPage_obj=mw.title.makeTitle(0,mainpage_msgobj:plain())
local curpage_obj=mw.title.getCurrentTitle()
--local curpage_redirectFrom_obj=curpage_obj.redirectTarget
--[[if curpage_redirectFrom_obj ~=false then
curpage_obj=curpage_redirectFrom_obj
end]]
return mw.title.equals(mainPage_obj,curpage_obj) --and curpage_obj.namespace==4
end
--确定页面存在
---exists是高开销方法,需要更高效的实现
--带保护的包装方法
--由于exists和解析器函数ifexist都是高开销方法
--而ifexist达到限制时默认返回结果为false的操作
--而exists会直接抛出错误而中断执行
--所以将相应调用包裹,压制exists的抛错,按照ifexist的理念,返回false
--正常情况下则一切正常
function ilh.isExist(pageName)
local execStatus,result=pcall(ilh._isExist,pageName)
if execStatus then
return result
else
return false
end
end
--真实方法
function ilh._isExist(pageName)
local localPage_obj=mw.title.makeTitle(0,pageName)
return localPage_obj.exists
end
--end
return ilh
f7db743d76a68ad6582c917defa3d289efa4ce88
Template:Link-ru
10
311
648
647
2024-08-05T14:52:57Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#Redirect [[Template:Internal link helper/ru]]
675abb3e5e500b242e1ae89d4cfd2ac1fe639d7d
Template:Internal link helper/ru
10
312
650
649
2024-08-05T14:52:57Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=ru |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation|Template:Internal link helper/doc}}</noinclude>
1161f8b9d160907c3a14c7a7e87642d707fda5d2
Template:Le
10
313
652
651
2024-08-05T14:52:57Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/en]]
{{短名重定向}}
{{模板重定向}}
866c4d05848633090eb9763d9c480ebe2c6b4fdf
Template:Internal link helper/ja
10
314
654
653
2024-08-05T14:52:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly>{{#invoke:ilh|main |lang-code=ja |1={{{1|{{{2|}}}}}} |2={{{2|}}} |d={{{d|{{{3|}}}}}} |nocat={{{nocat|}}}}}</includeonly><noinclude>{{Documentation|Template:Internal link helper/doc}}</noinclude>
878849200bafc1f6e2da1f4f33180f8c1c027bb7
Template:Link-ja
10
315
656
655
2024-08-05T14:52:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Internal link helper/ja]]
{{Pp-template|small=yes}}
{{Redirect category shell|1=
{{模板重定向}}
{{模板捷徑重定向}}
}}
02b0318a941508fba7a779c4f34ac6e9a358525c
Template:Color
10
316
658
657
2024-08-05T14:52:58Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<includeonly><span class=skin-invert style="color:{{{1}}};">{{{2}}}</span></includeonly><noinclude>{{doc}}</noinclude>
5b9c964e1a0a2ad063c467d4616047ed6cc08249
Template:Block
10
317
660
659
2024-08-05T14:52:59Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#if:{{NAMESPACE}}
| <!--
--><templatestyles src="Block/styles.css" /><!--
--><mark
class="skin-invert {{#switch: {{{4|{{{flag|}}}}}}
| sl = inline-text-block-sl
| hsd = inline-text-block-hsd
| hsl = inline-text-block-hsl
| inline-text-block-hd
}}"
title="{{#if: {{{2|}}} | {{{2}}} | 你知道的太多了}}"
style="background-color: {{#if: {{{color|{{{3|}}}}}}
| {{{color|{{{3}}}}}}
| {{#switch: {{{4}}}
| sl
| hsl = transparent
| #000000bf
}}
}}">{{{1}}}</mark>
| {{{1}}}
}}<noinclude>
{{Documentation}}</noinclude>
fcd75afadd7fc914e87c0bb8dcef2c6f6fd15a61
Template:Block/styles.css
10
318
662
661
2024-08-05T14:52:59Z
黑茶
2
导入1个版本
sanitized-css
text/css
.inline-text-blocked {
color: transparent !important;
background-color: #000000;
transition: color 0.25s;
}
.inline-text-blocked *, .inline-text-blocked a {
color: transparent !important;
background-color: transparent !important;
cursor: default !important;
text-decoration: none !important;
transition: color 0.25s !important;
}
.inline-text-blocked::selection, .inline-text-blocked *::selection {
color: #ffffff !important;
background: #404040;
background: rgba(0, 0, 0, 0.75);
}
@media (pointer: coarse) {
.inline-text-blocked:hover, .inline-text-blocked *:hover, .inline-text-blocked a:hover, .inline-text-blocked a:active, .inline-text-blocked a *:hover, .inline-text-blocked a *:active {
color: #ffffff !important;
}
}
@media (pointer: fine), (pointer: none) {
.inline-text-blocked:focus {
color: #ffffff !important;
}
}
/* hd = hard, dark */
.inline-text-block-hd {
color: transparent !important;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd a,
.inline-text-block-hd .new,
.inline-text-block-hd * {
color: transparent !important;
background: transparent !important
}
.inline-text-block-hd::selection,
.inline-text-block-hd *::selection {
color: #ffffff;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd a::selection {
color: #88bbff;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hd .new::selection {
color: #ffbb88;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
@media (pointer: coarse), (pointer: none) {
.inline-text-block-hd:hover,
.inline-text-block-hd:active,
.inline-text-block-hd:hover *,
.inline-text-block-hd:active * {
color: #ffffff !important;
transition: 0.15s linear
}
.inline-text-block-hd:hover a,
.inline-text-block-hd:active a {
color: #88bbff !important;
transition: 0.15s linear
}
.inline-text-block-hd:hover .new,
.inline-text-block-hd:active .new {
color: #ffbb88 !important;
transition: 0.15s linear
}
}
/* sl = soft, light */
.inline-text-block-sl,
.inline-text-block-sl a,
.inline-text-block-sl .new {
color: transparent !important
}
.inline-text-block-sl::selection {
color: #000000
}
.inline-text-block-sl a::selection {
color: #0033cc
}
.inline-text-block-sl .new::selection {
color: #cc3300
}
@media (pointer: coarse), (pointer: none) {
.inline-text-block-sl:hover,
.inline-text-block-sl:active {
color: #000000 !important;
transition: 0.15s linear
}
.inline-text-block-sl:hover a,
.inline-text-block-sl:active a {
color: #0033cc !important;
transition: 0.15s linear
}
.inline-text-block-sl:hover .new,
.inline-text-block-sl:active .new {
color: #cc3300 !important;
transition: 0.15s linear
}
}
/* hsd = hover-display, soft, dark */
.inline-text-block-hsd {
color: transparent !important;
background: #333333;
background: rgba(0, 0, 0, 0.8)
}
.inline-text-block-hsd a,
.inline-text-block-hsd .new {
color: transparent
}
.inline-text-block-hsd:hover,
.inline-text-block-hsd:active,
.inline-text-block-hsd::selection {
color: #ffffff !important;
transition: 0.15s linear
}
.inline-text-block-hsd:hover a,
.inline-text-block-hsd:active a,
.inline-text-block-hsd a::selection {
color: #88bbff;
transition: 0.15s linear
}
.inline-text-block-hsd:hover .new,
.inline-text-block-hsd:active .new,
.inline-text-block-hsd .new::selection {
color: #ffbb88;
transition: 0.15s linear
}
/* hsl = hover-display, soft, light */
.inline-text-block-hsl,
.inline-text-block-hsl a,
.inline-text-block-hsl .new {
color: transparent !important
}
.inline-text-block-hsl:hover,
.inline-text-block-hsl:active,
.inline-text-block-hsl::selection {
color: #000000 !important;
transition: 0.15s linear
}
.inline-text-block-hsl:hover a,
.inline-text-block-hsl:active a,
.inline-text-block-hsl a::selection {
color: #0033cc !important;
transition: 0.15s linear
}
.inline-text-block-hsl:hover .new,
.inline-text-block-hsl:active .new,
.inline-text-block-hsl .new::selection {
color: #cc3300 !important;
transition: 0.15s linear
}
583d9f3d313fba42040a2ced0572987f43964ead
Template:Purge
10
319
664
663
2024-08-05T14:53:00Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
[[Special:Purge/{{#if:{{{jumpto|}}}|{{{page|{{FULLPAGENAME}}}}}#{{{jumpto}}}|{{{page|{{FULLPAGENAME}}}}}}}|<span title="{{{2|更新-{zh-hans:服务器;zh-hant:伺服器;}-所-{zh-hans:缓存;zh-hant:快取;}-的页面数据}}}">{{{1|{{int:Purge}}}}}</span>]]<noinclude>{{Documentation}}</noinclude>
4e10b59a9ee84ebe25294f59511297f7821d1360
Template:Plain link
10
320
666
665
2024-08-05T14:53:01Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span class="plainlinks">{{#if:{{{2|{{{NAME|{{{name|}}}}}}}}}
|[{{{1|{{{URL|{{{url}}}}}}}}} {{{2|{{{NAME|{{{name|}}}}}}}}}]
|[{{{1|{{{URL|{{{url}}}}}}}}}]
}}</span><noinclude>
{{documentation}}
</noinclude>
5e02091166ecba7958ced6d8308fc3544ca974fa
Template:開玩笑的
10
321
668
667
2024-08-05T14:53:02Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
#REDIRECT [[Template:Jokes]]
713309a6d9aa0e4ea0f13380895bf9c6dd2f848d
Module:Rand
828
323
672
671
2024-08-05T14:53:03Z
黑茶
2
导入1个版本
Scribunto
text/plain
local func = {}
function func.randitem( frame )
local text = frame.args[1]
local list = mw.text.split(text, frame.args[2] or '[\n\r]%s*%*%s*')
math.randomseed(os.time())
local n = #list
local r = 0
if mw.text.trim(list[1]) == '' then
r = math.random(n - 1) + 1
else
r = math.random(n)
end
return mw.text.trim(list[r])
end
return func
0dae3ba1a3f32ddedce6ff88c3016f05a583abf5
User:Emojiwiki/username
2
324
674
673
2024-08-05T14:53:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span style="font-weight:bold;font-family:'Microsoft Yahei';"><span style="color:#003366">E</span><span style="color:#003399">m</span><span style="color:#000066">o</span><span style="color:#6600cc">j</span><span style="color:#660066">i</span><span style="color:#993366">w</span><span style="color:#993333">i</span><span style="color:#993300">k</span><span style="color:#663300">i</span></span>
991ba7070c6754da451133094108944c2bdc1d19
User:Emojiwiki/module/title
2
325
676
675
2024-08-05T14:53:03Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span style="font-weight:bold;font-family:'Microsoft Yahei';">{{U:Emojiwiki/username}}{{{1|}}}</span>
1ef527690562c628292067d26408b1ee7edeaa5a
Template:Script
10
326
678
677
2024-08-05T14:53:04Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
{{#switch: {{{1|}}}
<!--scripts with dedicated templates-->
|Arab = {{script/Arabic|1={{{2}}}}}
|fa-Arab = {{script/Nastaliq|1={{{2}}}|2=fa}}
|ps-Arab = {{script/Nastaliq|1={{{2}}}|2=ps}}
|ur-Arab = {{script/Nastaliq|1={{{2}}}}}
|Aran = {{script/Nastaliq|1={{{2}}}}}
|Armi = {{script/Aramaic|1={{{2}}}}}
|Avst = {{script/Avestan|1={{{2}}}}}
|Bali = {{script/Bali|1={{{2}}}}}
|Bamu = {{script/Bamum|1={{{2}}}}}
|Bhks = {{Script/Bhaiksuki|1={{{2}}}}}
|Brah = {{script/Brahmi|1={{{2}}}}}
|Bugi = {{script/Lontara|2={{{2}}}}}
|Buhd = {{script/Buhid|1={{{2}}}}}
|Copt = {{script/Coptic|1={{{2}}}}}
|Chak = {{script/Chakma|1={{{2}}}}}
|Cham = {{script/Cham|1={{{2}}}}}
|Cpmn = {{Script/Cypro-Minoan|1={{{2}}}}}
|Cyrs = {{script/Slavonic|1={{{2}}}}}
|Dupl = {{Script/Duployan|1={{{2}}}}}
|Ethi = {{script/Ethiopic|1={{{2}}}}}
|Geok = {{script/Khutsuri|1={{{2}}}}}
|Glag = {{script/Glagolitic|1={{{2}}}}}
|Goth = {{script/Gothic|1={{{2}}}}}
|Grek = {{script/Greek|1={{{2}}}}}
|Hebr = {{script/Hebrew|1={{{2}}}}}
|Ital = {{script/Old Italic|1={{{2}}}}}
|Java = {{script/Java|1={{{2}}}}}
|Kali = {{script/Kayah Li|1={{{2}}}}}
|Khmr = {{script/Khmer|1={{{2}}}}}
|Kits = {{Script/Khitan Small Script|1={{{2}}}}}<!-- 契丹小字 -->
|Latg = {{script/Gaelic|1={{{2}}}}}
|Lana = {{script/Tai Tham|1={{{2}}}}}
|Limbu = {{script/Limbu|1={{{2}}}}}
|Lisu|Fraser = {{script/Lisu|1={{{2}}}}}
|Marc = {{Script/Marchen|1={{{2}}}}}
|Meithei = {{script/Meithei|1={{{2}}}}}
|Mymr = {{script/Mymr|1={{{2}}}}}
|Newa = {{Script/Newa|1={{{2}}}}}
|Nkoo|Nko = {{script/Nko|1={{{2}}}}}
|Nshu = {{Script/Nushu|1={{{2}}}}}<!-- 女書 -->
|Perm = {{Script/Old Permic|1={{{2}}}}}
|Ogam = {{script/Ogam|1={{{2}}}}}
|Orkh = {{script/Orkhon|1={{{2}}}}}
|Osma = {{script/Osmanya|1={{{2}}}}}
|Phnx = {{script/Phoenician|1={{{2}}}}}
|Piqd = {{script/Klingon|1={{{2}}}}}
|Pollard = {{script/Pollard|1={{{2}}}}}
|Rjng = {{script/Rejang|1={{{2}}}}}
|Runr = {{script/Runic|1={{{2}}}}}
|Samr|Smrt = {{script/Samaritan|1={{{2}}}}}
|Sidd = {{script/Siddham|1={{{2}}}}}
|Sylo = {{script/Syloti|1={{{2}}}}}
|Syre = {{script/Strng|1={{{2}}}}}
|Syrj = {{script/Serto|1={{{2}}}}}
|Syrn = {{script/Mdnh|1={{{2}}}}}
|Tagb = {{script/Tagbanwa|1={{{2}}}}}
|Talu = {{script/New Tai Lue|1={{{2}}}}}
|Tavt = {{script/Tai Viet|1={{{2}}}}}
|Tglg = {{script/Baybayin|1={{{2}}}}}
|Tfng = {{script/Tifinagh|1={{{2}}}}}
|Vaii|Vai = {{script/Vai|1={{{2}}}}}
|Xsux = {{script/Cuneiform|1={{{2}}}}}
|Yiii|Yi = {{script/Yi|1={{{2}}}}}
<!--other scripts use standard language spans-->
|#default = <span {{#switch: {{{1}}}
<!--tweaks which should be moved to global CSS classes, with fonts supported in the Universal Language Selector-->
|Cprt = style="font-size:125%;font-family:'Segoe UI Historic','Noto Sans Cypriot', Code2001;"<!--SMP, rarely supported, state font explicitly-->
|Hano = style="font-size:125%;font-family:'Noto Sans Hanunoo', 'FreeSerif', Quivira;"
|Latf|de-Latf = style="font-size:125%;font-family:'Breitkopf Fraktur',UnifrakturCook,UniFrakturMaguntia,'MarsFraktur','MarsFraktur OT','KochFraktur','KochFraktur OT','OffenbacherSchwabOT';"
|en-Latf = style="font-size:125%;font-family:Cankama,'Old English Text MT','Textura Libera','Textura Libera Tenuis',London;"
|it-Latf = style="font-size:125%;font-family:'Rotunda Pommerania',Rotunda,'Typographer Rotunda';"
|th-Khom = style="font-size:200%;font-family:'SOV_jarukbali', 'Patimokka', 'KhomPaliForXP';"
|Linb = style="font-size:125%;font-family:'Noto Sans Linear B'"
<!-- |Smrt = style="font-size:125%;font-family:'Noto Sans Samaritan'" added above as Samr -->
|Ugar = style="font-size:125%;font-family:'Segoe UI Historic', 'Noto Sans Ugaritic', Aegean"
|Xpeo = style="font-size:125%;font-family:'Segoe UI Historic',Artaxerxes,Xerxes,Aegean;"<!--Use Xerxes for Old Persian-->
|#default = class="Unicode"<!--BMP, use generic "unicode" CSS class for all other scripts, including "Latn" for IPA-->
}}>{{{2}}}</span>
}}<noinclude>
{{template doc}}<!-- Add categories, documentation, and interwiki links to the /doc subpage, not here! -->
</noinclude>
ce29154979e43ecd528fb7c88fbdb574b0e3c91f
Module:Ilh/data
828
327
680
679
2024-08-05T14:53:04Z
黑茶
2
导入1个版本
Scribunto
text/plain
return {
['af'] = { ['lang'] = '南非语' },
['am'] = { ['lang'] = '阿姆哈拉语' },
['ami'] = { ['lang-hans'] = '阿美语', ['lang-hant'] = '阿美語' },
['ar'] = { ['lang-hans'] = '阿拉伯语', ['lang-hant'] = '阿拉伯語' },
['az'] = { ['lang'] = '阿塞拜疆语' },
['be'] = { ['lang'] = '白俄羅斯語' },
['be-tarask'] = { ['lang'] = '舊白俄羅斯語' },
['bg'] = { ['lang'] = '保加利亞語' },
['bho'] = { ['lang'] = '博杰普尔语' },
['bn'] = { ['lang'] = '孟加拉語' },
['bo'] = { ['lang'] = '藏语' },
['bs'] = { ['lang'] = '波斯尼亚语' },
['ca'] = { ['lang'] = '加泰罗尼亚语' },
['cdo'] = { ['lang'] = '閩東語' },
['ceb'] = { ['lang'] = '宿霧語' },
['ckb'] = { ['lang'] = '中库尔德语' },
['cs'] = { ['lang'] = '捷克語' },
['cv'] = { ['lang'] = '楚瓦什语' },
['cy'] = { ['lang'] = '威尔士语' },
['da'] = { ['lang'] = '丹麥語' },
['de'] = { ['lang'] = '德语' },
['diq'] = { ['lang'] = '扎扎其语' },
['el'] = { ['lang'] = '希臘語' },
['en'] = { ['lang-hans'] = '英语', ['lang-hant'] = '英語' },
['eo'] = { ['lang'] = '世界语' },
['es'] = { ['lang-hans'] = '西班牙语', ['lang-hant'] = '西班牙語' },
['et'] = { ['lang'] = '爱沙尼亚语' },
['eu'] = { ['lang'] = '巴斯克语' },
['fa'] = { ['lang'] = '波斯語' },
['fi'] = { ['lang'] = '芬蘭語' },
['fo'] = { ['lang'] = '法罗语' },
['fr'] = { ['lang-hans'] = '法语', ['lang-hant'] = '法語' },
['frp'] = { ['lang-hans'] = '阿尔卑坦语', ['lang-hant'] = '阿爾卑坦語' },
['ga'] = { ['lang'] = '愛爾蘭語' },
['gan'] = { ['lang'] = '赣语' },
['gl'] = { ['lang'] = '加利西亞語' },
['gor'] = { ['lang-hans'] = '哥伦打洛文', ['lang-hant'] = '哥倫打洛文' },
['gu'] = { ['lang'] = '古吉拉特語' },
['gv'] = { ['lang'] = '马恩语' },
['hak'] = { ['lang-hans'] = '客家话', ['lang-hant'] = '客家話' },
['he'] = { ['lang'] = '希伯來語' },
['hi'] = { ['lang'] = '印地語' },
['hr'] = { ['lang'] = '克羅地亞語' },
['ht'] = { ['lang'] = '海地克里奥尔语' },
['hu'] = { ['lang'] = '匈牙利语' },
['hy'] = { ['lang'] = '亞美尼亞語' },
['id'] = { ['lang'] = '印度尼西亚语' },
['inh'] = { ['lang-hans'] = '印古什文', ['lang-hant'] = '印古什文' },
['is'] = { ['lang'] = '冰島語' },
['it'] = { ['lang'] = '義大利語' },
['ja'] = { ['lang-hans'] = '日语', ['lang-hant'] = '日語' },
['ka'] = { ['lang'] = '格鲁吉亚语' },
['kk'] = { ['lang'] = '哈萨克语' },
['km'] = { ['lang-hans'] = '高棉语', ['lang-hant'] = '高棉語' },
['ko'] = { ['lang-hans'] = '朝鲜语', ['lang-hant'] = '韓語' },
['ku'] = { ['lang'] = '库尔德语' },
['ky'] = { ['lang'] = '柯爾克孜語' },
['la'] = { ['lang'] = '拉丁語' },
['lad'] = { ['lang'] = '拉迪诺语' },
['lb'] = { ['lang'] = '卢森堡语' },
['lo'] = { ['lang-hans'] = '老挝语', ['lang-hant'] = '寮語' },
['lt'] = { ['lang'] = '立陶宛语' },
['lv'] = { ['lang'] = '拉脫維亞語' },
['lzh'] = { ['lang'] = '文言文' },
['min'] = { ['lang'] = '米南加保语' },
['mk'] = { ['lang-hans'] = '马其顿语', ['lang-hant'] = '馬其頓語' },
['ml'] = { ['lang'] = '马拉雅姆语' },
['mn'] = { ['lang'] = '蒙古語' },
['ms'] = { ['lang'] = '馬來語' },
['mt'] = { ['lang'] = '马耳他语' },
['my'] = { ['lang'] = '缅甸语' },
['na'] = { ['lang'] = '瑙鲁语' },
['nan'] = { ['lang'] = '閩南語' },
['nds'] = { ['lang-hans'] = '低地德语', ['lang-hant'] = '低地德语' },
['ne'] = { ['lang'] = '尼泊尔语' },
['nl'] = { ['lang'] = '荷兰语' },
['no'] = { ['lang'] = '書面挪威語' },
['oc'] = { ['lang'] = '奥克语' },
['pl'] = { ['lang-hans'] = '波兰语', ['lang-hant'] = '波蘭語' },
['ps'] = { ['lang'] = '普什图语' },
['pt'] = { ['lang'] = '葡萄牙語' },
['qu'] = { ['lang-hans'] = '克丘亚语', ['lang-hant'] = '克丘亞語' },
['rm'] = { ['lang'] = '罗曼什语' },
['ro'] = { ['lang'] = '羅馬尼亞語' },
['ru'] = { ['lang'] = '俄语' },
['sa'] = { ['lang-hans'] = '梵语', ['lang-hant'] = '梵語' },
['sh'] = { ['lang'] = '塞爾維亞-克羅地亞語' },
['si'] = { ['lang'] = '僧伽罗语' },
['simple'] = { ['lang'] = '簡單英語' },
['sk'] = { ['lang'] = '斯洛伐克语' },
['sl'] = { ['lang'] = '斯洛維尼亞語' },
['smn'] = { ['lang-hans'] = '伊纳里萨米文', ['lang-hant'] = '伊納里薩米文' },
['so'] = { ['lang'] = '索馬利亞語' },
['sq'] = { ['lang'] = '阿尔巴尼亚语' },
['sr'] = { ['lang'] = '塞尔维亚语' },
['sv'] = { ['lang'] = '瑞典语' },
['sw'] = { ['lang'] = '斯瓦西裡語' },
['szy'] = { ['lang-hans'] = '撒奇莱雅语', ['lang-hant'] = '撒奇萊雅語' },
['ta'] = { ['lang'] = '泰米尔语' },
['tay'] = { ['lang-hans'] = '泰雅语', ['lang-hant'] = '泰雅語' },
['te'] = { ['lang'] = '泰卢固语' },
['tet'] = { ['lang-hans'] = '德顿语', ['lang-hant'] = '德頓語' },
['tg'] = { ['lang'] = '塔吉克语' },
['th'] = { ['lang'] = '泰语' },
['tk'] = { ['lang'] = '土库曼语' },
['tl'] = { ['lang'] = '他加禄语' },
['tr'] = { ['lang'] = '土耳其語' },
['tt'] = { ['lang'] = '韃靼語' },
['tyv'] = { ['lang'] = '图瓦语' },
['uk'] = { ['lang'] = '烏克蘭語' },
['ur'] = { ['lang'] = '烏爾都語' },
['uz'] = { ['lang'] = '烏孜別克语' },
['vi'] = { ['lang'] = '越南语' },
['wuu'] = { ['lang'] = '吴语' },
['xmf'] = { ['lang'] = '明格列尔语' },
['yue'] = { ['lang'] = '粵语' },
}
bf8c13ee2d381d1bbf44f7b305a9b6cefa6692ad
Template:Script/Tifinagh
10
328
682
681
2024-08-05T14:53:04Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<span class="script-tifinagh" style="font-family: 'DejaVu Sans', Ebrima, FreeSans, 'Noto Sans Tifinagh'">{{{1}}}</span><noinclude>
{{documentation}}
<!-- Add categories and interwikis to the /doc subpage, not here! -->
</noinclude>
c27b99d4ad79f86a6d26ff28d6c17fcfaa8efd1e
Template:Jokes
10
329
684
683
2024-08-05T14:53:05Z
黑茶
2
导入1个版本
wikitext
text/x-wiki
<noinclude>{{幽默}}</noinclude>{{{{{|safesubst:}}}#ifeq:{{{{{|safesubst:}}}NAMESPACE}}|{{{{{|safesubst:}}}ns:0}}||<span style="background:#ffffdd" title="本句仅作幽默目的,请勿当真。">{{{1|<noinclude>在此处填入幽默语句参数。请勿用作侮辱或人身攻击。</noinclude>}}}</span><sup>[[维基百科:坏笑话和删除的胡话|[{{{2|開玩笑的}}}]]]</sup>}}<noinclude>{{doc}}</noinclude>
4c7ca36a2fb7e1c9bdb9286b1eb6598b82f30feb
Template:每日一句/投稿
10
330
685
2024-08-05T15:01:45Z
黑茶
2
创建页面,内容为“*<!--欢迎光临 请以"星号“文字”——[[作者]]"的格式发布--> * 你们好!窝是饿裸狮的 ——[[那艺娜]]”
wikitext
text/x-wiki
*<!--欢迎光临 请以"星号“文字”——[[作者]]"的格式发布-->
* 你们好!窝是饿裸狮的 ——[[那艺娜]]
83526792392b9bac1f978cb5b18c49e40be4043d
Translations:那艺娜/Page display title/zh
1198
333
692
2024-08-18T04:04:45Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
那艺娜
05850ed3df8ce984841e379ada9e27cafd79a95b
Translations:那艺娜/1/zh
1198
334
693
2024-08-18T04:04:45Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
a7a1f12d5df6f74d499071699d8142d285822650
Translations:那艺娜/2/zh
1198
335
694
2024-08-18T04:04:45Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
ef881e204291ef50cd4027c2a735e8f482c0151c
Translations:那艺娜/3/zh
1198
336
695
2024-08-18T04:04:45Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
== 发展历程 ==
e459c8ab96373ea7e0d155466fce14b2699a8eb1
Translations:那艺娜/4/zh
1198
337
696
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
4825ef0610c1f098ec561e3ff5248b8b04d646b7
Translations:那艺娜/5/zh
1198
338
697
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
fd2058186b3a6bc08e2b676787985153c09b1cb6
Translations:那艺娜/6/zh
1198
339
698
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
b59de5ac795c0e5b741ea18ac529132ed04a22aa
Translations:那艺娜/7/zh
1198
340
699
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
== 发行歌曲 ==
6a64710d5b94974a1815aa422be32b01e7cccd98
Translations:那艺娜/8/zh
1198
341
700
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
* 《大贝塔》
b669a30ed2fdde5151348b99784eb46097bb19c1
Translations:那艺娜/9/zh
1198
342
701
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
== 参考资料 ==
3815fa7050f30032bd4a2b74086eceb36ffc40f0
Translations:那艺娜/10/zh
1198
343
702
2024-08-18T04:04:46Z
FuzzyBot
6
导入新版本自外部来源
wikitext
text/x-wiki
de64407ac7a39771bf2ee812e93423dfb9ec2061
Translations:那艺娜/Page display title/en
1198
331
690
2024-08-18T04:04:55Z
黑茶
2
创建页面,内容为“Na1Na”
wikitext
text/x-wiki
Na1Na
5d3e17de5fca09ab21280482d5ecb417a66382fb
那艺娜/en
0
332
691
2024-08-18T04:05:14Z
黑茶
2
创建页面,内容为“Na1Na”
wikitext
text/x-wiki
__INDEX__
<languages/>
<div lang="zh" dir="ltr" class="mw-content-ltr">
{{Infobox Douyin personality|name=那艺娜|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发展历程 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发行歌曲 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
* 《大贝塔》
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 参考资料 ==
</div>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<div lang="zh" dir="ltr" class="mw-content-ltr">
</div>
3ec96dd75dc654faa0c0fa11058be72b984790f7
704
691
2024-08-18T04:09:37Z
黑茶
2
创建页面,内容为“{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|cha…”
wikitext
text/x-wiki
__INDEX__
<languages/>
{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
<div lang="zh" dir="ltr" class="mw-content-ltr">
'''那艺娜'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),原名'''翟革英''',[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]人,中国内地流行音乐歌手。又被称为'''大贝塔娜娜''','''大橘瓣娜娜'''。那艺娜最初以“@'''俄罗斯娜娜'''”的身份在[[zhwp:抖音|抖音]]平台活动,以模仿外国[[zhwp:口音|口音]]和特效换伪装成俄罗斯人,通过贬损俄罗斯的方式夸赞中国,并对口型唱歌吸引关注,然后突然在抖音走红。吸引了一大堆粉丝,然后被抖音平台封杀。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发展历程 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发行歌曲 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
* 《大贝塔》
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 参考资料 ==
</div>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<div lang="zh" dir="ltr" class="mw-content-ltr">
</div>
575a8fe48ee880641a74a1b1ecdd9c8a8e4436a4
Translations:那艺娜/1/en
1198
344
703
2024-08-18T04:07:59Z
黑茶
2
创建页面,内容为“{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|cha…”
wikitext
text/x-wiki
{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
7b0b9d4b4d488ecbe9a79762a955e43e2819a284
User talk:黑茶
3
345
705
2024-08-18T04:28:00Z
香茶娜娜
7
创建页面,内容为“能给个管理吗?谢谢 --[[User:香茶娜娜|香茶娜娜]]([[User talk:香茶娜娜|留言]]) 2024年8月18日 (日) 12:27 (CST)”
wikitext
text/x-wiki
能给个管理吗?谢谢 --[[User:香茶娜娜|香茶娜娜]]([[User talk:香茶娜娜|留言]]) 2024年8月18日 (日) 12:27 (CST)
c9caf3e4c236e4aefdb44fc9af65dcb56915d614
706
705
2024-08-18T04:33:43Z
黑茶
2
wikitext
text/x-wiki
能给个管理吗?谢谢 --[[User:香茶娜娜|香茶娜娜]]([[User talk:香茶娜娜|留言]]) 2024年8月18日 (日) 12:27 (CST)
给了 --[[User:黑茶|黑茶]]([[User talk:黑茶|留言]]) 2024年8月18日 (日) 12:33 (CST)
4f3082f5ef99e1095d73e7bcffb40fb07b428ee6
707
706
2024-08-18T04:34:24Z
黑茶
2
wikitext
text/x-wiki
能给个管理吗?谢谢 --[[User:香茶娜娜|香茶娜娜]]([[User talk:香茶娜娜|留言]]) 2024年8月18日 (日) 12:27 (CST)
给了 --[[User:黑茶|黑茶]]([[User talk:黑茶|留言]]) 2024年8月18日 (日) 12:33 (CST)
c4b32c672b72627f8341eb219b53a9a581289013
708
707
2024-08-18T04:43:05Z
黑茶
2
wikitext
text/x-wiki
能给个管理吗?谢谢 --[[User:香茶娜娜|香茶娜娜]]([[User talk:香茶娜娜|留言]]) 2024年8月18日 (日) 12:27 (CST)
<br>
给了 --[[User:黑茶|黑茶]]([[User talk:黑茶|留言]]) 2024年8月18日 (日) 12:33 (CST)
69e04a0103aae8c1b8e9ec70ed49a2298704469b
Translations:那艺娜/2/en
1198
346
709
2024-08-18T05:08:02Z
黑茶
2
创建页面,内容为“'''贾吉'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),贾吉是一名来自中国南京的难民,为期两个月(生态社区)。据我所知,他是“Buta Nana”或“A…”
wikitext
text/x-wiki
'''贾吉'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),贾吉是一名来自中国南京的难民,为期两个月(生态社区)。据我所知,他是“Buta Nana”或“Alanzhi人系”。尼娜开始在提克托山顶上抱怨我是“俄罗斯的娜娜”,令人不安的奇怪冲动和赞美,尤其是在交流俄罗斯思想时。她害怕从录像带上对俄罗斯发出饥饿警告,组织对奇怪的生殖文化进行胁迫,然后突然间,人们发现了很多事情,然后她被打断了,依靠她作为提克托克学生的身份。
bbfe12e2f3b884d09af852ba308dd28868ccf47e
711
709
2024-08-18T05:08:21Z
黑茶
2
wikitext
text/x-wiki
'''Jia Ji'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),Jia Ji is a refugee from Nanjing, China, for a period of two months (ecological community). To my knowledge, he is of the "Buta Nana" or "Alanzhi ethnic group". Nina started complaining on the top of Mount Tiktok that I was the 'Nana of Russia', with unsettling strange impulses and compliments, especially when communicating Russian ideas. She was afraid of issuing hunger warnings to Russia from the videotape, organizing coercion against the strange reproductive culture, and then suddenly, people discovered many things, and then she was interrupted, relying on her identity as a Tiktok student.
5e9028b8a135c28401a4f6a454155b99f46500ca
那艺娜/en
0
332
710
704
2024-08-18T05:08:10Z
黑茶
2
创建页面,内容为“'''贾吉'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),贾吉是一名来自中国南京的难民,为期两个月(生态社区)。据我所知,他是“Buta Nana”或“A…”
wikitext
text/x-wiki
__INDEX__
<languages/>
{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''贾吉'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),贾吉是一名来自中国南京的难民,为期两个月(生态社区)。据我所知,他是“Buta Nana”或“Alanzhi人系”。尼娜开始在提克托山顶上抱怨我是“俄罗斯的娜娜”,令人不安的奇怪冲动和赞美,尤其是在交流俄罗斯思想时。她害怕从录像带上对俄罗斯发出饥饿警告,组织对奇怪的生殖文化进行胁迫,然后突然间,人们发现了很多事情,然后她被打断了,依靠她作为提克托克学生的身份。
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发展历程 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发行歌曲 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
* 《大贝塔》
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 参考资料 ==
</div>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<div lang="zh" dir="ltr" class="mw-content-ltr">
</div>
6381d841119000936d5f0f20c1fadf24207bec10
712
710
2024-08-18T05:11:21Z
黑茶
2
wikitext
text/x-wiki
__INDEX__
<languages/>
{{Infobox Douyin personality|name=Na1Na|birth_name=|birth_date={{birth date and age|1967|7|11}}|birth_place=[[zhwp:湖北省|湖北省]][[zhwp:荆门市|荆门市]][[zhwp:钟祥市|钟祥市]]|nationality=[[zhwp:中华人民共和国|中华人民共和国]]|occupation=网络红人、歌手|pseudonym=那艺娜(曾用俄罗斯娜娜、大中国娜娜)|genre=|channel_url=https://www.douyin.com/user/MS4wLjABAAAAdON8FxN3PQ5tcC52F7p0190M5KJt7dE5JKfKiLV5cdA|channel_display_name=那艺娜|subscribers=31.0万|subscriber_date=2024年7月4日}}
'''Jia Ji'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),Jia Ji is a refugee from Nanjing, China, for a period of two months (ecological community). To my knowledge, he is of the "Buta Nana" or "Alanzhi ethnic group". Nina started complaining on the top of Mount Tiktok that I was the 'Nana of Russia', with unsettling strange impulses and compliments, especially when communicating Russian ideas. She was afraid of issuing hunger warnings to Russia from the videotape, organizing coercion against the strange reproductive culture, and then suddenly, people discovered many things, and then she was interrupted, relying on her identity as a Tiktok student.
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发展历程 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发行歌曲 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
* 《大贝塔》
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 参考资料 ==
</div>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<div lang="zh" dir="ltr" class="mw-content-ltr">
</div>
9a8c996d7662a4cd9b649d37a4fc617fa89a8e3d
714
712
2024-08-18T05:12:23Z
黑茶
2
wikitext
text/x-wiki
__INDEX__
<languages/>
.
'''Jia Ji'''(1967年7月11日—<ref name="QQ音乐">{{cite web|title=那艺娜|url=https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|website=QQ音乐|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2023-04-09|archive-url=https://web.archive.org/web/20230409000126/https://y.qq.com/n/ryqq/singer/000LbHfi1z5SY4|dead-url=no}}</ref>),Jia Ji is a refugee from Nanjing, China, for a period of two months (ecological community). To my knowledge, he is of the "Buta Nana" or "Alanzhi ethnic group". Nina started complaining on the top of Mount Tiktok that I was the 'Nana of Russia', with unsettling strange impulses and compliments, especially when communicating Russian ideas. She was afraid of issuing hunger warnings to Russia from the videotape, organizing coercion against the strange reproductive culture, and then suddenly, people discovered many things, and then she was interrupted, relying on her identity as a Tiktok student.
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发展历程 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年该那艺娜以“俄罗斯娜娜 ”的身份入驻抖音平台,模仿外国口音和特效换伪装成俄罗斯人,并突然在抖音走红。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年,央视网发文“'''不要放过这个“娜娜‘’!'''”<ref>{{cite web|title=不要放过这个“娜娜”!|url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|website=央视网|accessdate=2024-07-04|language=zh-Hans-CN|archive-date=2024-07-04|archive-url=https://t.cj.sina.com.cn/articles/view/2090512390/7c9ab00602001weta|dead-url=no}}</ref>
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
2022年4月1日被抖音平台发现该人存在滥用平台道具、仿冒虚假人设的情况,抖音平台对账号“俄罗斯娜娜”进行无限期封禁的处罚。
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 发行歌曲 ==
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
* 《大贝塔》
</div>
<div lang="zh" dir="ltr" class="mw-content-ltr">
== 参考资料 ==
</div>
{{Reflist}}
[[Category:中国大陆网络红人]]
[[Category:短视频创作者]]
[[Category:中国男同性恋文化]]
[[Category:21世纪女歌手]]
[[Category:中国女歌手]]
[[Category:农村大妈{{#translation:}}]]
<div lang="zh" dir="ltr" class="mw-content-ltr">
</div>
0669b9aa044de3a34146fe6b0cd0f10153ab8dd2
Translations:那艺娜/1/en
1198
344
713
703
2024-08-18T05:11:36Z
黑茶
2
页面内容被替换为“.”
wikitext
text/x-wiki
.
3a52ce780950d4d969792a2559cd519d7ee8c727
那艺娜维基:超级管理员
4
5
715
7
2024-08-21T12:00:51Z
黑茶
2
重定向页面至[[zhwp:原神]]
wikitext
text/x-wiki
#重定向 [[zhwp:原神]]
c23bec6df5d0d9ecb954d1e43c202d9672415275
716
715
2024-08-21T12:04:10Z
黑茶
2
已移除至[[zhwp:原神]]的重定向
wikitext
text/x-wiki
[[原神|zhwp:原神]]
0a96db4f40334e706d14b7ce9b8b694c3b4aef8b
717
716
2024-08-21T12:07:45Z
黑茶
2
wikitext
text/x-wiki
[[zhwp:原神|原神]]
6c3e472afff56140393b0c20bcd45f25e5e321af